Skip to content

Package Model

Christian Presley edited this page Oct 9, 2026 · 5 revisions

Package Model

This page describes how the Zig package bridge_sdk holds the bridges. The package has one core module, bridge, and one module and one executable for each product. The key of a bridge is the name of its product, after a check of the brand guidelines that the vendor publishes. The package also exports the mcp module of zig-sdk. An embedder takes mcp from the package, so that it uses only one zig-sdk. The page also gives the steps to add a bridge and the record of each brand check.

Applies to: zig-bridge-sdk 0.1.2 on main at commit 3cbc34b, the commit of the tag v0.1.2, with the milestones M0 to M6. zig-sdk 0.5.1 at commit 52fc1b8, the commit of the tag v0.5.1. Zig 0.16.01.

The package

The repository is one Zig package2 with the name bridge_sdk. Its build.zig.zon has the version 0.1.2 and the minimum_zig_version 0.16.0. The only dependency is mcp, the package of zig-sdk. build.zig.zon pins it with a git+https URL with the commit 52fc1b8 of the tag v0.5.1, and with the hash of the package. The .paths list has build.zig, build.zig.zon, src, bridges, LICENSE, NOTICE and README.md.

Name Kind Root source file Imports
bridge Module src/bridge.zig mcp and build_options
vscode Module bridges/vscode/vscode.zig mcp and bridge
mcp Module The root of the pinned zig-sdk None
mcp-bridge-vscode Executable bridges/vscode/main.zig vscode, bridge and mcp

build_options gives the version of the package to bridge.version. mcp-bridge-vscode --version shows it. The initialize result also has it when the upstream server sends no server information. The build also makes two executables for the tests. bridge-fixture-server is the upstream server of the tests, and only the step fixture-server installs it. bridge-embedded-server is the same server with the vscode bridge in its process (M5), and only the step embedded-server installs it.

The Architecture page describes the modules of the core and the path of a request.

One module and one executable for each product

Each bridge has a key. The key names the directory bridges/<key>/, the module <key> and the executable mcp-bridge-<key>. The module declares the settings of the product as one bridge.Profile. The first bridge is for Visual Studio Code (VS Code), with the key vscode.

Part The vscode bridge
Directory bridges/vscode/
Module vscode, with the root bridges/vscode/vscode.zig
Executable mcp-bridge-vscode, with the root bridges/vscode/main.zig and the command line in bridges/vscode/cli.zig
Profile vscode.profile
OAuth identity vscode.identity: the client name mcp-bridge-vscode (zig-bridge-sdk), the keychain service zig-bridge-sdk/mcp-bridge-vscode and the token directory zig-bridge-sdk/vscode/tokens (M4)
Redirect port 41894 (M4)
Client ID metadata document site/vscode/client.json. GitHub Pages publishes it at https://christianpresley.github.io/zig-bridge-sdk/vscode/client.json, the value of vscode.client_metadata_url (M4).
API for a zig-sdk server vscode.serveStdio and vscode.StdioOptions (M5)
Tests bridges/vscode/test/, and the build step test-vscode
Run step run-vscode
README bridges/vscode/README.md

The product is a property of the executable. The core never chooses a profile from the clientInfo of the client, and the package has no generic profile. The .paths list, the fmt step and lint-docs include all of bridges/.

bridge.Profile

bridge.Profile in src/bridge.zig holds the settings of one product. bridge.Frontend and bridge.translate take it as *const Profile. vscode.serve gives &vscode.profile to Frontend.init.

Field Default Use Value in vscode.profile
name None The name of the executable. Each log line has it as its tag, and --version shows it. The initialize result has it when the upstream server sends no server information and the fallback name is empty. mcp-bridge-vscode
reply_protocol_version "2025-11-25" The protocolVersion of the initialize result3. The default
request_id_prefix "b-" The prefix of the string ids of the requests of the bridge to the client. The default
meta_passthrough.keys No keys The _meta keys of a client request that go to the upstream server. traceparent and tracestate
meta_passthrough.prefixes No prefixes The _meta key prefixes of a client request that go to the upstream server. vscode.
quirks.normalize_array_items false Each array schema of a tool inputSchema without items gets items: {}. true
quirks.drop_non_object_output_schema false Each tool loses an outputSchema whose root does not have type: "object". true
quirks.strict_legacy_results false Remove the values of revision 2026-07-28 that revision 2025-11-25 does not allow in a result. false

Profile.MetaPassthrough.allows gives true for a key in keys and for a key that starts with a prefix in prefixes. translate.passMeta then also removes each key that mcp.protocol.meta.validateKey refuses. It also removes each key of zig-sdk and each key with a reserved prefix.

The values of vscode.profile have these reasons, from the comments of bridges/vscode/vscode.zig:

  • normalize_array_items: the Copilot extension of VS Code stops each request when an array schema has no items4.
  • drop_non_object_output_schema: VS Code does not read the output schema. The TypeScript SDK 1.x refuses a tools/list result with an output schema that is not an object schema.
  • strict_legacy_results is off: VS Code reads the results of revision 2026-07-28, and the MCP Apps5 need them without a change.

These settings are not in the profile. bridge.Frontend.Options holds them for each connection:

  • capability_mask and reply_mask: the capabilities for the upstream server, and the capabilities for the initialize result.
  • fallback_name: the serverInfo.name when the upstream server sends none. mcp-bridge-vscode takes it from --name, from the file name of the upstream command without its extension, or from the host of the URL. The embedded bridge takes the name of the server.
  • timeouts, discover_timeout, max_line_bytes, json_max_depth, max_in_flight_requests, shutdown_grace and max_input_requests_per_round. The embedded bridge takes the limits from the server.
  • listen_backoff and listen_max_backoff: the waits before a new listen stream.
  • sign_in: the bridge.oauth.Authorizer of an HTTP upstream server (M4), or null.

Two more settings are not in the profile:

  • The OAuth identity (M4). bridge.oauth.Identity holds the client name, the keychain service, the product of the token directory and the default client ID metadata document. vscode.identity is the identity of the vscode bridge.
  • The discover option of the embedded bridge (M5). bridge.embed.Options.discover and vscode.StdioOptions.discover hold it: .answer, the default, or .refuse.

The mcp module and embedders

build.zig exports the mcp module of the pinned zig-sdk with b.modules.put(b.graph.arena, "mcp", mcp). In the source code, bridge.mcp and vscode.mcp are the same module. An embedder is a package that uses a bridge module and the mcp module together. From milestone M5, vscode.serveStdio puts the bridge into the executable of a zig-sdk server, and it takes the *mcp.Server of the package.

An embedder must use exactly one zig-sdk: the commit and the hash in the build.zig.zon of bridge_sdk. Do one of these steps:

  • Get mcp from the package: b.dependency("bridge_sdk", .{ .target = target, .optimize = optimize }).module("mcp") in build.zig. In the source code, @import("vscode").mcp is the same module.
  • Pin the zig-sdk commit and hash of bridge_sdk. Give b.dependency the same .target and .optimize arguments for zig-sdk and for bridge_sdk.

When the two mcp modules are not the same, Zig 0.16.0 shows one of these errors:

Error Cause
expected type '*mcp.server.Server', found '*mcp.server.Server' The package has a second zig-sdk, for example from a different commit. The types of the two mcp modules are then different.
file exists in modules 'mcp' and 'mcp0' The package pins the same zig-sdk, but it gives b.dependency different arguments. Zig then makes two mcp modules from the same files.

The example in examples/consumer/ takes vscode and mcp from the package. It is a zig-sdk server that calls vscode.serveStdio. A comptime check stops its build when vscode.mcp is not its mcp. The CI job consumer builds the example from a tarball of the commit, so the job also checks the .paths list.

A change of the zig-sdk pin is a minor release of zig-bridge-sdk. From milestone M5, the mcp types are a part of the public API of the vscode module. The repository file VERSIONING.md gives the rules of the pin.

Steps to add a bridge for a new product

  1. Read the brand guidelines and the trademark guidelines that the vendor of the product publishes.
  2. Select the key from the result of that check.
  3. Record the result, the URL and the date of the check in the section Brand checks.
  4. Make the directory bridges/<key>/ for all files of the bridge.
  5. Write the module bridges/<key>/<key>.zig. Declare pub const profile: bridge.Profile and a serve function.
  6. In the module, export mcp and bridge again, as bridges/vscode/vscode.zig does.
  7. For the URL form, declare pub const identity with bridge.oauth.Identity.of.
  8. Give the bridge its own redirect port. The vscode bridge uses the port 41894.
  9. Put the client ID metadata document of the bridge in site/<key>/client.json, with a test.
  10. Write a serveStdio function that calls bridge.embed.serveStdioAuto with the profile of the bridge.
  11. Write a short bridges/<key>/main.zig. Set std_options.logFn to bridge.log.tagged(profile.name).
  12. Use the exit codes of mcp-bridge-vscode: 0 at the end of stdin, 1 for a failure, 2 for bad arguments.
  13. In build.zig, add the module <key> with the imports mcp and bridge.
  14. In build.zig, add the executable mcp-bridge-<key> and the steps run-<key> and test-<key>.
  15. Add the tests of the module and of the executable to the step test.
  16. Write transcript tests in bridges/<key>/test/. Give them the vendored schemas with addSchemaImports in build.zig.
  17. Check each frame of the bridge against the schemas of the two revisions.
  18. Write bridges/<key>/README.md with the build, the configuration of the client and the trademark notice.
  19. Write a wiki page for the bridge. Add a row to the table of bridges on Home.
  20. Add the entries of the bridge to CHANGELOG.md under [Unreleased], with the key as the part.
  21. Run zig build fmt test lint-docs.

The command line parser of the vscode bridge is in bridges/vscode/cli.zig. The plan moves the shared parts of the command line into the core only when a second product comes.

Brand checks

Before a key goes into the names of a bridge, the project reads the brand guidelines of the vendor. This section records each check. A record is not legal advice.

vscode

Item Record
Product Visual Studio Code (VS Code), from Microsoft
Guidelines The brand guidelines of VS Code6, and the trademark guidelines of Microsoft7
URL https://code.visualstudio.com/brand and https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks
Date of the check 2026-10-06
Result The brand page does not allow the product name in the name of a product or service, on a website or in a domain name. For content that works with VS Code, it approves names of the form <name> for Visual Studio Code. The trademark guidelines of Microsoft ask for a trademark notice. They do not allow text that suggests an affiliation with Microsoft or an endorsement by Microsoft. The brand page also asks writers not to use the forms vscode, VSCode, VSC or Code for the product.
Decision The approved plan of the project, 2026-10-06. Keep the key vscode for the module, the directory bridges/vscode/ and the executable mcp-bridge-vscode. Add a trademark notice.

The decision came before milestone M0, because M0 made these names. A later change of the key changes the paths in VS Code configurations, the imports of embedders and the groups of released changelog entries. The project applies these rules for the decision:

  • Prose writes "Visual Studio Code (VS Code)" at the first mention on a page, and "VS Code" after it.
  • Prose writes the key, the module and the executable only as code spans. The project dictionary has vscode and vsc as synonyms of VS Code, so lint-docs finds them in plain prose.
  • Titles use the form <name> for Visual Studio Code, for example "The vscode bridge for Visual Studio Code".
  • The trademark notice is in README.md, in bridges/vscode/README.md, in the doc comment of bridges/vscode/vscode.zig and in the footer of this wiki.

The notice has this text:

Visual Studio Code and VS Code are trademarks of Microsoft Corporation. This project has no affiliation with Microsoft, and Microsoft does not endorse it.

This record is not legal advice.

References

  1. ZIG-0.16-RELNOTES: Zig 0.16.0 release notes.
  2. ZIG-BUILD-GUIDE: The build system of Zig.
  3. MCP-CHANGELOG-2025-11-25: Key changes of revision 2025-11-25.
  4. VS Code issue 339276: An array parameter without items blocks the tools of a server.
  5. MCP-EXT-APPS: The MCP Apps extension.
  6. Visual Studio Code brand guidelines: The brand page of VS Code, with the rules for the product name.
  7. Microsoft trademark guidelines: The rules of Microsoft for the use of its trademarks.

Clone this wiki locally