{"slug":"architecture/MCP_AND_PLUGIN_PUBLISHING_SPEC","title":"MCP Connector, MCP Pool and Plugin Publishing","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/MCP_AND_PLUGIN_PUBLISHING_SPEC.mdx","bytes":17103,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n**Status:** Proposed\n**Document type:** Specification\n**Authority:** Subordinate to [`INTEGRATEWISE_ARCHITECTURE.md`](../../architecture/INTEGRATEWISE_ARCHITECTURE.md)\n**Canonical sections implemented:** §15.1 (Profile-gated exposure) · §16.1 (Nineteen tools) · §16.2 (Distribution names) · §16.3 (Distribution) · §17 (Environments)\n**Owner:** Platform\n**Version:** 1.0\n**Last verified against:** HEAD `d941a422`\n**Last verified date:** 2026-07-31\n\n---\n\n## 1. Three things that are constantly confused\n\nThey all contain the letters M-C-P. They are not the same layer, and only one of them is\never published.\n\n|            | **MCP Connector**                                                                                        | **MCP Pool**                                                                                                                 | **Plugin / MCP Marketplace**                                 |\n| ---------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |\n| What it is | The **public boundary**. Hosts the exact 19 semantic tools plus the OAuth authorization server           | The **internal operator control plane**. `register` · `unregister` · `capabilities` · `health` · `invoke` over internal MCPs | A **distribution channel**                                   |\n| Service    | `services/mcp-connector`                                                                                 | `services/mcp-pool`                                                                                                          | —                                                            |\n| Endpoint   | `mcp.integratewise.ai` (prod) · `mcp.test.integratewise.ai` (test)                                       | Internal binding only                                                                                                        | —                                                            |\n| Audience   | Every external consumer                                                                                  | Operators, in `development` and `customer_zero` only                                                                         | Prospective customers                                        |\n| Published? | **The endpoint is referenced** by every published manifest. The service is _deployed_, never distributed | **Never.** Not a tool surface, not a public route, not a routing target in any manifest                                      | **Publishes a package** that binds to the Connector endpoint |\n\n**The rule, in one line:**\n\n> **Pool is a control plane. Connector is the boundary. Marketplace is a channel.\n> Nothing published ever names the Pool.**\n\n### 1.1 \"Pool for Customer Zero, MCP for external\" — the correct and incorrect readings\n\nThis framing recurs, so both readings are recorded here with the evidence that separates them.\n\n**Correct — exposure.** Pool's _administration surface_ is exposed in `development` and\n`customer_zero`, and not exposed in `external`. This is §15.1 and it is right.\n\n**Incorrect — substitution.** Pool as Customer Zero's _tool surface_ in place of the public\nMCP. Two reasons it fails, the second decisive:\n\n_It breaks parity._ Customer Zero exists to exercise the exact external contract. Exercise a\ndifferent surface and it proves nothing about the external experience.\n\n_It is not possible._ Verified at HEAD: `services/mcp-pool/src` contains **zero** of the 19\nsemantic tools. It exposes five lifecycle verbs — `register` · `unregister` · `capabilities`\n· `health` · `invoke` — over nine platform-management namespaces: `provider.*` · `apps.*` ·\n`connections.*` · `oauth.*` · `connectors.*` · `sync.*` · `webhooks.*` · `schemas.*` ·\n`tasks.*`. A Customer Zero running on Pool could not use IntegrateWise. It could only\nadminister it.\n\n**They are two different jobs, not two sizes of one thing.**\n\n|                          | Job                    | Surface                                   | Available to                                                               |\n| ------------------------ | ---------------------- | ----------------------------------------- | -------------------------------------------------------------------------- |\n| **IW-Spine-Network MCP** | _Use the product_      | The 19 semantic tools                     | Everyone — `development`, `customer_zero`, `external` — **byte-identical** |\n| **MCP Pool**             | _Operate the platform_ | 5 lifecycle verbs over 9 admin namespaces | Operators only — `development` and `customer_zero`                         |\n\nExternal users do not receive \"less MCP.\" They receive the **whole product** and **no\noperator plane**, because they do not operate the platform. Customer Zero receives the same\nwhole product _plus_ the operator plane, because it does.\n\n**The test, in one question:** does Customer Zero call `get_my_focus` through\n`mcp.integratewise.ai`, or through Pool? Only the first preserves parity — and per the code\nabove, only the first is possible.\n\n### 1.2 Why the Pool can never be published\n\nTwo independent reasons, either sufficient:\n\n**It breaks Customer Zero parity.** Customer Zero exists to exercise the exact external\ncontract. If Customer Zero routes through Pool while external routes through the public\nsurface, Customer Zero stops proving anything about the external experience — which is its\nonly purpose.\n\n**It is the wrong layer.** Pool binds `PROVIDER_MANAGEMENT`, `INTEGRATION_MANAGEMENT`,\n`TASK_MANAGEMENT` and `SPINE` and exposes lifecycle verbs over them. It is a registry and\nrouter for internal MCPs. It is not a semantic tool surface and cannot substitute for one.\n\nThe correct statement, which resolves **D6**:\n\n> The public MCP surface is **byte-identical across all three profiles**. MCP Pool is an\n> operator control plane whose _administration UI_ is exposed only in `development` and\n> `customer_zero`. Pool is never a tool surface and never a per-profile alternative to MCP.\n\n---\n\n## 2. What gets published, per channel\n\n| Channel                                          | Published artifact                                                                                                          | Binds to                         |\n| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |\n| **MCP registries / directories**                 | **IW-Spine-Network MCP** — remote server reference, exact 19-tool manifest, optional UI resources, browser Workbench launch | `mcp.integratewise.ai`           |\n| **Plugin directories / AI app stores**           | **IW-Spine-Network Plugin** — MCP-backed app, focused UI resources, workflow skills                                         | `mcp.integratewise.ai`           |\n| **Vercel / developer marketplaces**              | Channel-native listing plus the inbound provider connector where required                                                   | Gateway + `mcp.integratewise.ai` |\n| **Provider marketplaces** (GitHub, Notion, Coda) | Provider-native app **only** where provider OAuth, installation, webhook or sync semantics require it                       | Gateway as a tenant connection   |\n\nBoth primary artifacts are **channel packages over one contract**. Neither is a different\nbackend, and neither exposes a different tool set.\n\n### 2.1 Connectors are not distribution packages\n\nA provider connector (Notion, Slack, Salesforce) is a **catalogue entry**, not a published\ndistribution artifact. It appears in the connector marketplace _inside_ the product. It is\nnot listed in an external MCP registry as though it were an IntegrateWise product.\n\nThis distinction is currently blurred in `releases/` — see F4.\n\n---\n\n## 3. Blocking findings\n\nVerified at HEAD `d941a422` on 2026-07-31. **Each of these blocks submission.**\n\n### F1 · The public MCP domain has two claimants\n\n`services/mcp-connector/wrangler.toml`:\n\n```toml\nname   = \"integratewise-mcp-connector\"                                    # line 1\nroutes = [{ pattern = \"mcp.integratewise.ai\", custom_domain = true }]     # line 6\n\n[env.prod]\nname   = \"mcp-connector-prod\"                                            # line 224\nroutes = [{ pattern = \"mcp.integratewise.ai\", custom_domain = true }]     # line 226\n```\n\n**The top-level Worker and `env.prod` claim the same custom domain.** Whichever deploys last\nowns it. The URL a marketplace manifest would point at therefore has an ambiguous owner, and\na routine deploy of the default environment silently repoints the public endpoint.\n\n`validate-platform-deployment.sh` asserts only that `mcp-connector-test` and\n`mcp-connector-prod` both exist. **Existence is not uniqueness** — this collision passes the\ncheck.\n\n_Fix:_ remove the top-level `routes` block; only `env.test` and `env.prod` bind domains.\nExtend the validator to assert that no two Workers claim the same route pattern.\n\n### F2 · The published manifest advertises 23 tools; the contract is 19\n\n`marketplace/apps/iw-spine-network.json`:\n\n```\ndescription : \"…Installs the full 23-tool continuity network — 20 operational c…\"\ntools        : 19 entries\n```\n\nVerified independently: `services/mcp-connector/src` defines exactly **19** unique tool names.\n\nThe 23 comes from `marketplace/index.json` — 20 operational + 3 cognitive **connectors**.\nSomeone counted connectors and wrote \"tools.\" The array is right; the sentence a reviewer\nreads is wrong.\n\nThis is stop-ship invariant #2: _\"the public MCP lists anything other than the exact 19\ntools.\"_ A manifest whose own description contradicts its own tool array will not survive\nreview, and shouldn't.\n\n_Fix:_ correct the description. Add a test asserting `tools.length === 19` **and** that no\npublished string claims a different count.\n\n### F3 · The public manifest names MCP Pool as its routing target\n\n```json\n\"ownership\": { \"credentials\": \"provider\", \"metadata\": \"integratewise\", \"routing\": \"mcp-pool\" }\n```\n\nThe public artifact declares the **internal operator control plane** as its route. Either it\nis accurate — in which case the public path runs through a plane that must never be public —\nor it is inaccurate, since the real public route is `mcp-connector`. Both readings block\nsubmission, and the second also leaks internal topology into a customer-facing file.\n\n_Fix:_ `\"routing\": \"mcp-connector\"`. Add a manifest test that fails on any occurrence of\n`mcp-pool`, `spine-cache`, worker names, service bindings or internal hostnames in any file\nunder `marketplace/`.\n\n### F4 · MCP Pool has no test surface, and dev binds production\n\n`services/mcp-pool/wrangler.toml` declares `[env.dev]` and `[env.prod]` — **no `[env.test]`**.\nAll environments, including `dev`, bind:\n\n```toml\nservice = \"integratewise-integration-management-mcp-prod\"\n```\n\nThe development control plane talks to a production service. This violates §17 environment\nisolation on the component with the most privilege in the system, and there is no test\nsurface on which to prove otherwise.\n\n_Fix:_ add `[env.test]`; repoint each environment at its own suffixed target; include\n`mcp-pool` in the binding-isolation assertion.\n\n### F5 · A retired product name is staged for publication\n\n`marketplace/apps/iw-continuity-bridge.json` is present in the publishable directory.\n`IW Continuity Bridge` is a retired public name (**D9**). Publishing it revives a superseded\nidentity in a permanent, externally-indexed location.\n\n_Fix:_ delete or move out of `marketplace/`. Resolve D9 first if the name is genuinely still\nwanted.\n\n### F6 · Five release flavours against a two-package doctrine\n\n`releases/` contains `iw-spine-network-v1.0.0-20260725` as: `chatgpt-plugin` ·\n`claude-connector` · `js-sdk` · `mcp-server` · `notion-integration`.\n\nDoctrine (§16.2) names two published packages plus the SDK. `claude-connector` and\n`notion-integration` are either channel packages needing the canonical names, or provider\nconnectors being shipped as though they were distribution artifacts (§2.1). Five artifacts\nunder one version string with no stated mapping to the two-package model is how a reviewer —\nor a customer — concludes there are five products.\n\n_Fix:_ map every flavour to exactly one of `IW-Spine-Network Plugin`,\n`IW-Spine-Network MCP`, `@integratewise/sdk`, or _catalogue connector — not published\nexternally_. Delete what does not map.\n\n---\n\n## 4. Publishing gates\n\nNo submission to any marketplace until **all** of the following hold.\n\n**Contract**\n\n- [ ] The deployed endpoint lists exactly 19 tools, verified against the live protected resource\n- [ ] The transport URL is verified from the deployed resource — never taken from a document\n- [ ] No manifest string claims a tool count other than 19\n- [ ] No published file references `mcp-pool`, internal worker names, service bindings, D1/KV/R2 names or internal hostnames\n\n**Routing and isolation**\n\n- [ ] Exactly one Worker claims `mcp.integratewise.ai` (F1)\n- [ ] `mcp-connector-test` and `mcp-connector-prod` exist, with distinct routes and distinct bindings\n- [ ] `mcp-pool` has `test` and `prod` surfaces, each bound to its own suffixed targets (F4)\n- [ ] No `env.test` target equals any `env.prod` target, for any binding class\n\n**Behaviour**\n\n- [ ] OAuth completes end to end against the deployed resource\n- [ ] The onboarding state machine reaches `active`, with `consent_required` enforced\n- [ ] A host without MCP App UI support receives meaningful text/JSON and can launch the browser Workbench\n- [ ] No automatic inheritance of unrelated host-app credentials\n- [ ] One governed action completes: proposal → approval token → execution → receipt → reconciliation\n\n**Persistence** — the gate that currently fails\n\n- [ ] Canonical writes land in Neon and a failed or skipped write cannot return `success` (architecture **S0**)\n\n**Naming**\n\n- [ ] Only `IW-Spine-Network Plugin`, `IW-Spine-Network MCP` and `IW Spine Tools` appear as published names\n- [ ] No retired name is present in `marketplace/` (F5)\n- [ ] Every artifact in `releases/` maps to exactly one canonical package (F6)\n\n---\n\n## 5. Publication invariants\n\n1. **MCP Pool is never published, referenced, routed to, or named in any external artifact.**\n2. The public surface is byte-identical across `development`, `customer_zero` and `external`.\n3. Exactly 19 tools. UI resources are additive and add no tools.\n4. Exactly one Worker owns each public route.\n5. Installing a package never clones Customer Zero data, credentials, memory, cache, queues or audit.\n6. A provider connector is a catalogue entry, not an external distribution artifact.\n7. A manifest's transport URL is verified against the deployed resource before submission.\n8. Listing copy is bound by the claims register and must state that consequential action requires approval.\n\n---\n\n## 6. Current state\n\n| Element                                   | State                                                                      |\n| ----------------------------------------- | -------------------------------------------------------------------------- |\n| 19-tool contract in code                  | **Implemented** — 19 unique tools verified in `services/mcp-connector/src` |\n| Public endpoint routing                   | **Broken** — two claimants on `mcp.integratewise.ai` (F1)                  |\n| Published manifest                        | **Broken** — claims 23 tools; names `mcp-pool` as routing (F2, F3)         |\n| MCP Pool isolation                        | **Broken** — no test surface; dev binds prod (F4)                          |\n| Retired names in `marketplace/`           | **Present** (F5)                                                           |\n| `releases/` ↔ package doctrine            | **Unmapped** — five flavours, two packages (F6)                            |\n| Canonical persistence behind the endpoint | **Broken** — architecture **S0**                                           |\n\n**Nothing is submittable today.** F1 through F4 are each a few lines of configuration or copy;\nS0 is the substantive one. The cheap fixes are worth doing in one pass because every one of\nthem is the kind of defect a marketplace reviewer finds in the first ten minutes — and a\nrejected submission costs a resubmission window, not just a patch.\n\n---\n\n**Related:** [Architecture §15.1, §16](../../architecture/INTEGRATEWISE_ARCHITECTURE.md) ·\n[Marketplace Channels and Data Flow Spec](MARKETPLACE_CHANNELS_AND_DATA_FLOW_SPEC.md) ·\n[IW-Spine-Network Plugin and MCP Marketplace Contract](../../architecture/IW_SPINE_NETWORK_PLUGIN_AND_MCP_MARKETPLACE_CONTRACT.md)\n"}