Blog
Tutorials

Bidirectional MCP: the marketplace and the exposed RAG

Bidirectional MCP: the marketplace's external servers become agent skills while the built-in server exposes the workspace RAG to IDEs - fallback, health, pins. F-MCP-1.

Simmetric Team8 min read15/10/2026
Bidirectional MCP: the marketplace and the exposed RAG

The assistant that meets the tools halfway MCP has two directions, and most implementations only tell you about one

MCP has two directions, and most integrations only tell you about one. In the connect direction, you bring EXTERNAL MCP servers into the workspace and their tools become callable during chats - no code, no redeploy. In the expose direction, Simmetric Chat turns itself inside out: a built-in MCP server serves the workspace's own RAG search to EXTERNAL clients - your IDEs, wherever your developers already work.

This article walks both directions plus the control surfaces that make them safe to operate: the marketplace install flow, the manual connections, the per-chat pinning, the transport fallback, and the health checks.

The marketplace's write operations are admin-gated (browsing needs only a signed-in user). Facts per FACT-CENSUS.md F-MCP-1.

The connect direction: the marketplace

The MCP Marketplace is a curated catalog of external MCP servers. Browsing the catalog (list + detail) needs just authentication; the write arms - creating entries and installing into a workspace - are admin-only. The install flow is atomic and self-contained:

  1. The schema validates the install payload (a workspace + an optional name/headers override - the headers pass a write-side blocklist check that rejects hop-by-hop keys, enforces a name allowlist, and caps sizes).
  2. The entry must exist (404) and must not already be installed in that workspace (409).
  3. The workspace-scoped connection row gets created with the catalog's URL and transport.
  4. The event lands in the audit log (mcp.installed), and the connector spins up fire-and-forget: a connect failure is logged, never silently swallowed into a "healthy" state.

Uninstalling is the inverse: the tools' registrations drop, the connection hard-deletes, and the audit entry lands (mcp.uninstalled). Installation is thus reversible with zero residue.

External tools become agent skills

Once connected, each external server's tools register into the agent's skill registry under collision-free names (mcp_<connection>_<tool>). The registry resolves per chat:

  • No pins - every enabled connection of the workspace lends its tools.
  • Pins present - only the pinned AND enabled AND in-scope connections do; the pin set can never REMOVE tools (it only adds - the strict union with the workspace-scoped tools stays).

The per-chat pinning is the operation's steering wheel: a compliance chat can talk to exactly the tools it should, without affecting the rest of the workspace.

The expose direction: your IDE reaches the RAG

The built-in MCP server exposes the platform's retrieval to external clients:

  • `rag_query` - searches the workspace's documents (the grounded, cited search the internal chat uses).
  • `list_workspaces` - the client-side discovery arm.

The transport is the stateless Streamable HTTP endpoint (the current MCP core revision, JSON-only responses); the legacy SSE transport remains with a deprecation grace. Authentication has two shapes: with MCP_API_KEY set, a bearer check (a miss or a wrong key = 401); unset, the server falls back to loopback-only - remote callers get a 401 rather than unauthenticated access. The IDE story: your developer's editor reaches the same grounded document search the chat surface reaches - the knowledge base is one corpus with many doors.

The operational rails

Three mechanisms keep the two directions operable rather than merely enabled:

  • Transport fallback - a connection declared streamable falls back to SSE on a 4xx rejection (never on a 5xx - a server error must not silently degrade the transport); a connection declared SSE-only stays SSE.
  • Health checks - a pg-boss cron cycles the installed + enabled connections every 30 minutes, ping with exponential retry, and tracks a status ladder (healthy → stale on the first failures → down from the third) with the failure details kept per connection.
  • The connection mutex + status map - connect/disconnect serialize per connection; the live statuses come from the running state, not the database, so a "test" reflects the truth of the moment.

The audit class

Every marketplace and connection mutation logs to the event log (mcp.installed / mcp.uninstalled / the CRUD arms) - the platform's immutable activity log carries the surface (per F-AUDIT-1), matching the operator story of the rest of the platform.

Reading on

The guide carries the complete reference - the catalog fields, install/uninstall flows, the pinning semantics, the expose-side transports - at /en/docs/mcp-marketplace:

Provenance: Simmetric Chat docs/MCP_MARKETPLACE.md + packages/server/src/agent/mcpServer.ts/mcpClient.ts (the transports + the fallback), services/mcpHealthCheckJob.ts, CHANGELOG.md v0.28.1 - at the census's pinned docs state (SHA aca5b8ff).

Related articles