Skip to content

feat(mcp): add MCP tool surface for the full X client API#6

Merged
teslashibe merged 1 commit into
mainfrom
feat/mcp-integration
Apr 22, 2026
Merged

feat(mcp): add MCP tool surface for the full X client API#6
teslashibe merged 1 commit into
mainfrom
feat/mcp-integration

Conversation

@teslashibe

Copy link
Copy Markdown
Owner

Summary

Adds a new ./mcp subpackage built on github.com/teslashibe/mcptool v0.1.0 that exposes every exported *x.Client method as an MCP tool with a typed input struct. Each tool's JSON input schema is reflected from struct tags, so there is no hand-maintained schema and no drift between this package's API and what an agent sees.

The structure mirrors linkedin-go/mcp (just merged via teslashibe/linkedin-go#9): one Provider, one tool-group file per logical area, one shared Excluded map of intentional non-exposures with reasons.

Tools (37)

Reads (19)

  • Profile / identity: x_get_profile, x_get_profile_by_id, x_me
  • Social graph: x_get_followers, x_get_following
  • Tweets: x_get_tweet, x_get_tweet_detail, x_get_user_tweets
  • Timelines: x_home_timeline, x_home_latest_timeline
  • Search: x_search_tweets, x_search_users, x_advanced_search_tweets
  • DMs: x_get_conversations, x_get_conversation
  • Lists: x_get_list, x_get_list_timeline, x_get_list_members
  • Analysis: x_scrape_timeline_trends

Writes (18)

  • Compose: x_create_tweet, x_reply, x_quote_tweet, x_delete_tweet
  • Engagement: x_like, x_unlike, x_retweet, x_unretweet, x_bookmark, x_unbookmark
  • Social: x_follow, x_unfollow, x_mute, x_unmute, x_block, x_unblock
  • DM: x_send_dm, x_send_new_dm

All tools use snake_case x_<verb>_<noun> names and have descriptions ≤ 120 chars (enforced by TestToolsValidate). List-returning tools use mcptool.PageOf so the host's response middleware can uniformly cap and surface next_cursor. Write tools return { "ok": true, ...key fields... } on success.

Excluded (13)

Internal / lifecycle helpers — surfaced via the host application's middleware, not as agent-callable tools:

Method Reason
RateLimit observability surfaced via the host's MCP middleware
TransactionInitErr bootstrap state reported at construction
RefreshQueryIDs internal session-bootstrap helper

Convenience wrappers around the corresponding *Page variant — exposed as a single cursor-aware tool to keep the surface compact while retaining pagination:

HomeTimeline, HomeLatestTimeline, UserTweets, SearchTweets, SearchUsers, AdvancedSearchTweets, GetFollowers, GetFollowing, GetListTimeline, GetListMembers.

Drift prevention

mcp/mcp_test.go runs mcptool.Coverage(reflect.TypeOf(&x.Client{}), Provider{}.Tools(), Excluded) and fails when:

  • an exported method on *x.Client is neither wrapped by a tool nor listed in Excluded (Missing)
  • Excluded references a method that no longer exists (UnknownExclusions)

Current report: 37 wrapped, 13 excluded, 0 missing, 0 unknown exclusions.

Tools also pass mcptool.ValidateTools (canonical name regex, ≤ 120-char description, non-nil Invoke and InputSchema, no duplicates) and the x_ prefix check.

CI

Adds .github/workflows/mcp-ci.yml. On any push to main or PR touching mcp/**, **/*.go, go.mod, go.sum, or the workflow itself:

  1. go mod tidy — must produce no diff
  2. go vet ./...
  3. go build ./...
  4. go test -race -count=1 ./mcp/...

Guardrails respected

  • No changes to existing tests or non-MCP code
  • Go toolchain version in go.mod unchanged (1.25.5)
  • Only new dependency: github.com/teslashibe/mcptool v0.1.0 (and its transitive deps)
  • All write methods are exposed (no policy gating in the package — that's the host's job)

Test plan

  • go vet ./... clean
  • go build ./... clean
  • go test -race -count=1 ./mcp/... green locally
  • Coverage test reports 0 missing, 0 unknown exclusions
  • All 37 tool names validate; descriptions ≤ 120 chars; x_ prefix
  • CI green on this PR

Refs: teslashibe/agent-setup#6

Adds a new ./mcp subpackage built on github.com/teslashibe/mcptool that
exposes every exported *x.Client method as an MCP tool with a typed input
struct. Each tool's JSON input schema is reflected from struct tags so
there's no hand-maintained schema and no drift.

A coverage test (TestEveryClientMethodIsWrappedOrExcluded) iterates the
exported method set on *x.Client and fails if a new method is added that
is neither wrapped nor explicitly listed in mcp.Excluded with a reason —
keeping the MCP surface in lockstep with the package API is enforced by
CI rather than convention.

Tools (37):
  reads:  x_get_profile, x_get_profile_by_id, x_me,
          x_get_followers, x_get_following,
          x_get_tweet, x_get_tweet_detail, x_get_user_tweets,
          x_home_timeline, x_home_latest_timeline,
          x_search_tweets, x_search_users, x_advanced_search_tweets,
          x_get_conversations, x_get_conversation,
          x_get_list, x_get_list_timeline, x_get_list_members,
          x_scrape_timeline_trends
  writes: x_create_tweet, x_reply, x_quote_tweet, x_delete_tweet,
          x_like, x_unlike, x_retweet, x_unretweet,
          x_bookmark, x_unbookmark,
          x_follow, x_unfollow, x_mute, x_unmute, x_block, x_unblock,
          x_send_dm, x_send_new_dm

Excluded (13):
  internal/lifecycle:
    RateLimit          — observability surfaced via host MCP middleware
    TransactionInitErr — bootstrap state reported at construction
    RefreshQueryIDs    — internal session-bootstrap helper
  convenience wrappers around the *Page variant exposed as a single
  cursor-aware tool:
    HomeTimeline, HomeLatestTimeline, UserTweets, SearchTweets,
    SearchUsers, AdvancedSearchTweets, GetFollowers, GetFollowing,
    GetListTimeline, GetListMembers

Coverage: 37 wrapped, 13 excluded, 0 missing, 0 unknown exclusions.

Adds .github/workflows/mcp-ci.yml gating PRs on `go mod tidy` cleanliness,
`go vet`, `go build`, and `go test -race ./mcp/...`. Updates README with
an "MCP support" section.

Refs: teslashibe/agent-setup#6
@teslashibe teslashibe merged commit d801ec0 into main Apr 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant