Repository navigation
feat(apps): connector-github, GitHub's remote MCP server as an open-edition connector app (E4 batch 1, GitHub half) - #28306
Conversation
…dition connector app A declarative mcp instance (http transport, X-MCP-Readonly, include allowlist of search_issues and issue_read), a bearer credentialRef, two flows using it, the listing file and an administrator README. Tested by a boot through bootStack against a fake MCP client. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…pins the unset-credential run ESM package (import.meta under NodeNext); the README states what an under-scoped classic token does, as measured on both credential paths. The lockfile drops the Stripe importer: that app waits on a decision. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…ce and quiet the registry log check:test-source-alias and check:registry-log-declared, both red on the first gate run, both green after. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 4ebf1b9a79269f78b5859e68b4c038cae2b3ed97 && git checkout 4ebf1b9a79269f78b5859e68b4c038cae2b3ed97
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 53749673ba7a0005d09e8a79544da10d5faa10bc cf30e616111bfe1b44a6a1a5bf203319ba8f33cf && git checkout -B drift-repro 53749673ba7a0005d09e8a79544da10d5faa10bc && git merge --no-ff cf30e616111bfe1b44a6a1a5bf203319ba8f33cf
node scripts/docs-audit/affected-docs.mjs --json 53749673ba7a0005d09e8a79544da10d5faa10bc
|
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U 席位核对ACCEPT at head
Open items, not this PR: listing identity Landing: not governed: the seat lands it now ( |
Part of #28276
Clause-②: no
Metadata-protocol: none
维护者速读
packages/apps/connector-github,一个开源版连接器应用:把 GitHub 的远程 MCP 服务器声明为mcp连接器(只读请求头,白名单只放search_issues、issue_read两个读工具),令牌经credentialRef由管理员提供、不进元数据;附两个用它的流程、上架文件和写给管理员的 README。--include-pattern只算出白名单、不裁剪文档,实测输出 63,317,655 字节、612 个操作(用到的只有 6 个),卡上要求的「脚本打印的 sha256」和「保持小」做不到同时成立,走法等卡上裁决,所以本 PR 用Part of不关卡。pnpm install。packages/apps/connector-github/src/connectors/github.connector.ts(URL、请求头、白名单、凭据引用);②packages/apps/connector-github/test/boot.test.ts(假 MCP 客户端上的整栈启动,走一遍管理员设凭据的路径);③packages/apps/connector-github/README.md的 Credentials 一节。pnpm --filter @objectstack/connector-app-github test,应看到Validation passed和Tests 10 passed (10)。What changes
One new npm-private workspace package under the existing
packages/apps/*glob,@objectstack/connector-app-github(packages/apps/connector-github/), and its entry inpnpm-lock.yaml. No other file changes.src/connectors/github.connector.ts), written as recipe 2 ofskills/objectstack-automation/references/integration-recipes.mdteaches:provider: 'mcp', http transport tohttps://api.githubcopilot.com/mcp/with theX-MCP-Readonly: trueheader,providerConfig.include: ['search_issues', 'issue_read'], andauth: { type: 'bearer', credentialRef: 'GITHUB_MCP_TOKEN' }. The URL, the read-only header and theAuthorization: Bearer TOKENform come from GitHub's own documentation (github/github-mcp-serveratf2a07cd1,docs/remote-server.mdand the README's remote configuration), and thereposcope both tools need comes from the same README's per-tool scope lines.src/flows/github.flows.ts):github_search_issues(inputquery, outputsearch.content) andgithub_get_issue(inputsowner,repo,issue_number, outputissue.content).objectstack.config.ts):type: 'app', namespacegithub,requires: ['automation'], and the zero-argumentConnectorMcpPlugininplugins:, the way the scaffolded template lists its executors.objectstack.manifest.json) and the README the listing points at. Its credentials section namesGITHUB_MCP_TOKEN, where to get it and the permissions it needs, as the marketplace handbook asks.testscript isobjectstack validate && vitest run, so the run CI makes oftestrunsos validatefirst. No CI step runs a package'svalidatescript on its own.Tests
On head
cf30e616:pnpm --filter @objectstack/connector-app-github testgivesValidation passed, thenTest Files 2 passed (2)andTests 10 passed (10).pnpm --filter @objectstack/connector-app-github typecheckexits 0.test/boot.test.tsboots the app withbootStack(@objectstack/verify), which is howobjectstack servecomposes it. The only substitution is the MCP client, swapped in by plugin name throughextraPlugins, so no call reaches GitHub. It checks the administrator's path in order:github_mcpisdegraded, the reason namesGITHUB_MCP_TOKEN, and nothing is dialled.400FLOW_FAILED, the message names the reference, and nothing is dialled.PUT /api/v1/automation/connectors/credential-refs/GITHUB_MCP_TOKENbrings the instance toready. Its actions are exactlyissue_readandsearch_issues, although the fake server also listsissue_write. The transport dialled is GitHub's URL withX-MCP-Readonly: trueandAuthorization: Bearerplus the fixture token.POST /api/v1/automation/NAME/trigger.test/listing.test.tschecks the listing file. It parses againstTemplateManifestSchema, itsmanifestIdequals the stack'smanifest.id, and it declares no key that publish ignores. The README's## Credentialssection names everycredentialRefthe stack declares, and no connector carries a secret.OS_REGISTRY_LOG: 'warn'. The suite's[Registry]lines went from 247 to 0.Acceptance notes
normalize-openapi --inStripespec3.jsonat51610f5f, with an include pattern selecting 6 GET operations, writes 63,317,655 bytes holding all 612 operations, sha2560ea3c37a….--include-patterncomputes theincludelist and trims nothing, and--max-depth 0still writes 6,070,551 bytes with all 612 operations. So "the packaged spec is the script's output, its sha256 in the README" and recipe 1's "trim the vendor's document to the operations the app calls" cannot both hold with the script as it is.reposcope. GitHub's server hides every tool the token's scopes do not cover (docs/scope-filtering.md), and anincludeentry the server does not list is a configuration fault. I probed this once, throughbootStackagainst a fake server listing onlyget_me; the probe is not committed. With the value in the environment variable, the whole boot is refused. With the value in the credential store, the instance stays degraded and is told to "fix its declaration". A secondPUTwith a well-scoped value recovers it with no restart. The README states both outcomes as measured.check:template-manifestswalks onlypackages/create-objectstack/src/templates, so this file is parsed by the package's ownlisting.test.tsinstead.Verification
Gate families that read this diff (60 of 60, all exit 0, head cf30e61)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 60 commands (48 by path, 6 by change kind, 8 whole-tree). Every one ran with its exit code captured before any pipe.--ranreconciliation:60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN, a derived zero.On the first run (head
fbb7b6a2), two gates were red on this package's test setup:check:test-source-alias(dist-resolved test imports) andcheck:registry-log-declared(a bootStack suite with noOS_REGISTRY_LOG). Both are fixed incf30e616and green. None of the 60 assumes a published platform app:check:published-filesandcheck:changeset-fixedboth pass with the package private.Not run locally
test:repoand the repository-wide scans (pnpm lintfirst among them) belong to CI. The dogfood battery does not apply: the title has no!and there is no narrowing arm.Generated by Claude Code