@shipstatic/mcp 1.0.0-beta.0 → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -85,7 +85,7 @@ Same config format — `npx @shipstatic/mcp`. Works with any MCP-compatible clie
85
85
 
86
86
  ## Free API key — permanent deployments
87
87
 
88
- `SHIP_TOKEN` is optional. Without it, deploys behave like the hosted endpoint (public, claim URL, 3-day expiry). With it, you get permanent deployments, the full toolset, and bigger limits.
88
+ `SHIP_TOKEN` is optional. Without it, deploys behave like the hosted endpoint (public, claim URL, expire in 3 days). With it, you get permanent deployments, the full toolset, and bigger limits.
89
89
 
90
90
  Get a free API key at [my.shipstatic.com/api-key](https://my.shipstatic.com/api-key):
91
91
 
@@ -102,7 +102,7 @@ The hosted endpoint exposes `deployments_upload` only. The local install exposes
102
102
  | Tool | Description | Hosted |
103
103
  |------|-------------|:---:|
104
104
  | `deployments_upload` | Publish files and get a live URL instantly, optionally protected by a password | ✓ |
105
- | `deployments_list` | List all deployments with their URLs, status, labels, and password protection state | |
105
+ | `deployments_list` | List all deployments with their URLs, status, labels, and password protection state. Pages with `limit` and `cursor` | |
106
106
  | `deployments_get` | Get deployment details including URL, status, file count, size, labels, and password protection state | |
107
107
  | `deployments_set` | Update the labels on a deployment for organization and filtering | |
108
108
  | `deployments_delete` | Permanently delete a deployment and all its files | |
@@ -112,7 +112,7 @@ The hosted endpoint exposes `deployments_upload` only. The local install exposes
112
112
  | Tool | Description |
113
113
  |------|-------------|
114
114
  | `domains_set` | Connect a custom domain to your site, switch deployments, or update labels |
115
- | `domains_list` | List all domains with their linked deployment and verification status |
115
+ | `domains_list` | List all domains with their linked deployment and verification status. Pages with `limit` and `cursor` |
116
116
  | `domains_get` | Get domain details including linked deployment, verification status, and labels |
117
117
  | `domains_records` | Get the DNS records you need to configure at your DNS provider |
118
118
  | `domains_dns` | Look up which DNS provider hosts a domain (e.g. Cloudflare, Namecheap) |
@@ -127,6 +127,16 @@ The hosted endpoint exposes `deployments_upload` only. The local install exposes
127
127
  |------|-------------|
128
128
  | `whoami` | Get your account details including email, plan, and usage |
129
129
 
130
+ ### Paging
131
+
132
+ `deployments_list` and `domains_list` accept `limit` and `cursor`. Each response carries a `cursor` — pass it back to fetch the next page; `null` means you are on the last one.
133
+
134
+ ### Retrying a deploy safely
135
+
136
+ `deployments_upload` accepts an `idempotencyKey`. If a deploy times out you cannot tell "it never landed" from "it landed and the response was lost", and retrying without a key creates a second site. Send the same key on the retry and the original deployment is returned instead.
137
+
138
+ Key the *attempt*, not the try — a run id, a commit sha, or a uuid generated before the first call. A key that changes on every retry does nothing.
139
+
130
140
  ## Registry
131
141
 
132
142
  Published to the [MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=com.shipstatic/mcp) as `com.shipstatic/mcp`. Registry-aware clients see both the hosted endpoint and the local install and pick the right transport for their environment.
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * THE EXECUTABLE — `dist/bin.js`, the file `npx @shipstatic/mcp` runs. It is
4
+ * the only module here with side effects on import.
5
+ *
6
+ * `index.ts` beside it is a library and stays inert, which is what lets the
7
+ * hosted transport import this package's vocabulary instead of re-authoring
8
+ * it. The two used to be one file: `main` and `bin` in `package.json` both
9
+ * pointed at `index.ts`, so importing the package started a stdio server and,
10
+ * on failure, called `process.exit` in its consumer. Nothing could be shared
11
+ * because there was nothing importable to share. `npm/ship` split the same
12
+ * knot the same way (`bin.ts` executable, `index.ts` library) — a module
13
+ * boundary says the same thing to every caller.
14
+ */
15
+ import { createRequire } from 'node:module';
16
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
17
+ import Ship from '@shipstatic/ship';
18
+ import { SHIP_ENV } from '@shipstatic/types';
19
+ import { createServer } from './server.js';
20
+ // The executable knows its own manifest; the library it drives does not have
21
+ // to. `createServer` takes the version as an argument precisely so no module
22
+ // below this one needs `node:module` in its import graph.
23
+ const { version } = createRequire(import.meta.url)('../package.json');
24
+ async function main() {
25
+ // SHIP_TOKEN is optional — without it, deployments are public (3-day expiry).
26
+ // The SDK coerces empty strings to undefined, so we can pass through directly.
27
+ //
28
+ // One credential slot, any platform token: the value's prefix says what it
29
+ // is (`ship-` API key, `deploy-` deploy token, anything else an opaque
30
+ // bearer) and the server classifies it. MCP never has to know which kind it
31
+ // holds.
32
+ const ship = new Ship({ token: process.env[SHIP_ENV.TOKEN] });
33
+ // No `via` — this executable IS the `mcp` origin, which is the default.
34
+ const server = createServer(ship, { version });
35
+ const transport = new StdioServerTransport();
36
+ await server.connect(transport);
37
+ console.error('ShipStatic MCP Server running on stdio');
38
+ }
39
+ main().catch((error) => {
40
+ console.error('Fatal error:', error);
41
+ process.exit(1);
42
+ });
package/dist/call.d.ts CHANGED
@@ -1,2 +1,51 @@
1
1
  import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
- export declare function call<T>(fn: () => Promise<T>): Promise<CallToolResult>;
2
+ /**
3
+ * The two error arms that earn a hint. Everything else relays verbatim — a
4
+ * hint on any other type sends the agent chasing a credential that is not the
5
+ * problem.
6
+ *
7
+ * They are ARGUMENTS rather than constants because they are the one part of
8
+ * the mapping that legitimately differs per transport: stdio can name the
9
+ * environment variable it owns, and the hosted endpoint deliberately cannot
10
+ * (it has no configuration of its own, and naming another package's variable
11
+ * is how this pair silently desynchronised once already).
12
+ */
13
+ export interface ErrorHints {
14
+ /** Appended after `Hint: ` when the SDK rejects the credential. */
15
+ authentication: string;
16
+ /** Appended after `Hint: ` when the platform refuses an authenticated call. */
17
+ forbidden: string;
18
+ }
19
+ /**
20
+ * The wrapper every tool handler delegates to. Named because the shared
21
+ * toolset takes it as an argument: the tools are identical across transports,
22
+ * the hints inside `call` are not.
23
+ */
24
+ export type CallFn = <T>(fn: () => Promise<T>) => Promise<CallToolResult>;
25
+ export interface CallOptions {
26
+ hints: ErrorHints;
27
+ /**
28
+ * Attach a plain-object SUCCESS result as `structuredContent` beside the
29
+ * text. Hosted-only: it is what feeds the Apps-SDK widget, and the MCP spec
30
+ * pairs it with an `outputSchema`, which is a hand-maintained zod twin of a
31
+ * published type. One such twin is worth it for a widget; fifteen would be a
32
+ * drift surface with no consumer asking for it. See
33
+ * `cloudflare/mcp/CLAUDE.md`, "What deliberately differs".
34
+ *
35
+ * It does NOT gate the ERROR envelope, which every transport carries — see
36
+ * `toErrorResult`. The objection above is about fifteen success shapes; a
37
+ * failure has exactly one published shape, and no schema to keep in step.
38
+ */
39
+ structuredContent?: boolean;
40
+ }
41
+ /**
42
+ * Builds the `call()` wrapper both transports use: SDK promise in, MCP
43
+ * `CallToolResult` out.
44
+ *
45
+ * The success envelope, the `'Done.'` sentinel for a void result, the order
46
+ * the error arms are tested in, and the `Details:` appendix are all wire
47
+ * facts an agent observes — so they live here once, rather than in two files
48
+ * kept equal by review.
49
+ */
50
+ export declare function createCall(options: CallOptions): CallFn;
51
+ export declare const call: CallFn;
package/dist/call.js CHANGED
@@ -1,33 +1,88 @@
1
1
  import { ErrorType, isShipError } from '@shipstatic/ship';
2
- export async function call(fn) {
3
- try {
4
- const result = await fn();
5
- const text = result === undefined ? 'Done.' : JSON.stringify(result, null, 2);
6
- return { content: [{ type: 'text', text }] };
7
- }
8
- catch (error) {
9
- return handleError(error);
10
- }
2
+ /**
3
+ * Builds the `call()` wrapper both transports use: SDK promise in, MCP
4
+ * `CallToolResult` out.
5
+ *
6
+ * The success envelope, the `'Done.'` sentinel for a void result, the order
7
+ * the error arms are tested in, and the `Details:` appendix are all wire
8
+ * facts an agent observes — so they live here once, rather than in two files
9
+ * kept equal by review.
10
+ */
11
+ export function createCall(options) {
12
+ const { hints, structuredContent = false } = options;
13
+ return async function call(fn) {
14
+ try {
15
+ const result = await fn();
16
+ // A void SDK method has nothing to serialize; every other result is the
17
+ // wire shape verbatim, because an agent reads exactly what the API sent.
18
+ if (result === undefined) {
19
+ return { content: [{ type: 'text', text: 'Done.' }] };
20
+ }
21
+ const text = JSON.stringify(result, null, 2);
22
+ const structured = structuredContent && isPlainObject(result)
23
+ ? result
24
+ : undefined;
25
+ return {
26
+ content: [{ type: 'text', text }],
27
+ ...(structured ? { structuredContent: structured } : {}),
28
+ };
29
+ }
30
+ catch (error) {
31
+ return toErrorResult(error, hints);
32
+ }
33
+ };
34
+ }
35
+ function isPlainObject(value) {
36
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
11
37
  }
12
- function handleError(error) {
38
+ /**
39
+ * The failure envelope: authoritative prose, with the wire's own structure
40
+ * riding beside it.
41
+ *
42
+ * The TEXT is unchanged and stays the contract — hints included. It has to be:
43
+ * the API authors its messages for the end user at the throw site
44
+ * (`cloudflare/api/CLAUDE.md`, "Message authoring law"), so the sentence
45
+ * always contains what the agent needs, and a client that ignores everything
46
+ * else still works.
47
+ *
48
+ * `structuredContent` carries `ShipError.toResponse()` verbatim — the same
49
+ * `ErrorResponse` the wire itself uses. Until 1.0.0-beta.8 the typed contract
50
+ * terminated here: `status`, `ErrorType`, and every `details` payload except
51
+ * the Validation arm's were dropped, so the platform's own law — *clients
52
+ * branch on error type and status, never on message strings* — held for every
53
+ * consumer EXCEPT the one best equipped to obey it. The recorded bite was a
54
+ * 429: `details.expires` died at this boundary, leaving the caller most in
55
+ * need of a precise backoff to parse "try again in 9 minutes" out of English.
56
+ *
57
+ * Safe on every arm, and checked rather than assumed: the MCP SDK validates
58
+ * `structuredContent` only when a tool declares an `outputSchema`, and returns
59
+ * early again when `isError` is set. No tool here declares one. So this is
60
+ * additive for every client and invisible to any that does not look.
61
+ *
62
+ * It is deliberately NOT behind `CallOptions.structuredContent` — that flag
63
+ * governs success shapes, where the schema-twin objection lives. A failure has
64
+ * one published shape on every transport.
65
+ */
66
+ function toErrorResult(error, hints) {
13
67
  if (isShipError(error)) {
14
68
  let message = error.message;
15
69
  if (error.isType(ErrorType.Authentication)) {
16
- message +=
17
- '\n\nHint: Set a free SHIP_TOKEN environment variable in your MCP server configuration.';
70
+ message += `\n\nHint: ${hints.authentication}`;
18
71
  }
19
72
  if (error.isType(ErrorType.Forbidden)) {
20
- message +=
21
- '\n\nHint: This action is not permitted. Likely cause: plan limits reached or the account is terminated. Stop retrying — the user needs to upgrade or contact support at https://my.shipstatic.com.';
73
+ message += `\n\nHint: ${hints.forbidden}`;
22
74
  }
23
75
  if (error.isType(ErrorType.Validation) && error.details) {
24
76
  message += `\n\nDetails: ${safeStringify(error.details)}`;
25
77
  }
26
78
  return {
27
79
  content: [{ type: 'text', text: message }],
80
+ structuredContent: { ...error.toResponse() },
28
81
  isError: true,
29
82
  };
30
83
  }
84
+ // No structure for a non-ShipError: there is no wire shape to report, and
85
+ // inventing one would tell an agent this failure came from the platform.
31
86
  const fallback = error instanceof Error ? error.message : 'An unexpected error occurred';
32
87
  return {
33
88
  content: [{ type: 'text', text: fallback }],
@@ -42,3 +97,9 @@ function safeStringify(value) {
42
97
  return String(value);
43
98
  }
44
99
  }
100
+ /** stdio's hints: this package owns `SHIP_TOKEN` and is the only side that may name it. */
101
+ const STDIO_HINTS = {
102
+ authentication: 'Set a free SHIP_TOKEN environment variable in your MCP server configuration.',
103
+ forbidden: 'This action is not permitted. Likely cause: plan limits reached or the account is terminated. Stop retrying — the user needs to upgrade or contact support at https://my.shipstatic.com.',
104
+ };
105
+ export const call = createCall({ hints: STDIO_HINTS });
package/dist/index.d.ts CHANGED
@@ -1,2 +1,64 @@
1
- #!/usr/bin/env node
2
- export {};
1
+ /**
2
+ * The library entry — importing this file has NO side effects.
3
+ *
4
+ * `bin.ts` is the executable; this is what a consumer imports. There are two
5
+ * such consumers: the hosted Streamable-HTTP transport in the platform's
6
+ * private `cloudflare/mcp`, and the VS Code extension
7
+ * (`integrations/vscode`), which bundles a stdio server into its `.vsix`.
8
+ * Both transports are converging on the same product — the complete toolset
9
+ * for authenticated callers, the anonymous deploy for everyone else — and
10
+ * "one product, two transports" is only true if one of them can import the
11
+ * other.
12
+ *
13
+ * **The surface is exactly what a SECOND CONSUMER needs — nothing more.**
14
+ * That is the rule, and it is stricter than "curated". It read "a second
15
+ * TRANSPORT" until 1.0.0-beta.7, when the VS Code extension arrived as a
16
+ * consumer that is not a transport: it wants stdio's own composition,
17
+ * verbatim, running on the user's machine. The wording widened; the strictness
18
+ * did not.
19
+ *
20
+ * Every name below answers a question a consumer must otherwise answer for
21
+ * itself, and each admission was a restatement deleted, not a convenience
22
+ * added: `SERVER_NAME` and `UPLOAD_TOOL_NAME` were literals in two repos (the
23
+ * first also correlates the Apps-SDK widget to the connector), `PUBLIC_EXPIRY`
24
+ * was the same duration written out eight times, `DESCRIPTION_BLOCKS` the
25
+ * fragments two tool descriptions genuinely share, `ACCOUNT_TOOL_NAMES` is
26
+ * what lets the hosted catalogue fence name the fourteen without counting them
27
+ * again, and `createServer` deleted three regexes in another repo's build (see
28
+ * below).
29
+ *
30
+ * **`createServer` is exported; the configured `call` is not.** The extension
31
+ * previously reached stdio's composition by REGEX-PATCHING this package's
32
+ * compiled `dist/` at bundle time — stripping `bin`'s shebang, and rewriting
33
+ * the `createRequire(import.meta.url)('../package.json')` line inside
34
+ * `server.js` to inline a version literal. Three hacks against another
35
+ * package's build output, each of which the 1.x library split broke. A short
36
+ * entry point calling `createServer(ship, { version, via })` replaces all of
37
+ * them, which is a restatement deleted rather than a convenience added.
38
+ * `call` stays internal because a consumer configures its own hints through
39
+ * `createCall`, and stdio's instance is not a contract anyone needs.
40
+ *
41
+ * Its second argument is the HOST's own facts — the version it reports and the
42
+ * deploy origin its uploads carry — because a library has no manifest to read
43
+ * and no idea which product it was installed inside. A `startStdio` absorbing
44
+ * the transport as well was proposed and rejected; `CLAUDE.md` records why, and
45
+ * `tests/architecture/worker-safety.test.ts` is the fence that makes the reason
46
+ * mechanical rather than remembered.
47
+ *
48
+ * The old reason for withholding `createServer` — that its upload tool takes a
49
+ * filesystem PATH, a footgun to offer a Worker — is still true and is now the
50
+ * CALLER's judgement rather than an absence: `cloudflare/mcp` must keep
51
+ * authoring its own upload tool, and does. An absence cannot express "correct
52
+ * for one consumer, wrong for another"; a documented rule can. What makes the
53
+ * export safe to publish at all is that `createServer` takes its `version` as
54
+ * an ARGUMENT — so exporting it adds no `node:module` to the import graph of a
55
+ * module the Workers-hosted transport loads.
56
+ *
57
+ * `tests/index.test.ts` fences both directions — nothing missing, nothing
58
+ * extra — because adding an export is the quiet failure: everything published
59
+ * becomes a breaking change to remove.
60
+ */
61
+ export { type CallFn, type CallOptions, createCall, type ErrorHints } from './call.js';
62
+ export { createServer } from './server.js';
63
+ export { ACCOUNT_TOOL_NAMES, registerAccountTools } from './tools.js';
64
+ export { ANNOTATIONS, DESCRIPTION_BLOCKS, INSTRUCTION_BLOCKS, PARAM_DESCRIPTIONS, PUBLIC_EXPIRY, SERVER_NAME, UPLOAD_TOOL_NAME, } from './vocabulary.js';
package/dist/index.js CHANGED
@@ -1,22 +1,64 @@
1
- #!/usr/bin/env node
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import Ship from '@shipstatic/ship';
4
- import { createServer } from './server.js';
5
- async function main() {
6
- // SHIP_TOKEN is optional without it, deployments are public (3-day expiry).
7
- // The SDK coerces empty strings to undefined, so we can pass through directly.
8
- //
9
- // One credential slot, any platform token: the value's prefix says what it
10
- // is (`ship-` API key, `deploy-` deploy token, anything else an opaque
11
- // bearer) and the server classifies it. MCP never has to know which kind it
12
- // holds.
13
- const ship = new Ship({ token: process.env.SHIP_TOKEN });
14
- const server = createServer(ship);
15
- const transport = new StdioServerTransport();
16
- await server.connect(transport);
17
- console.error('ShipStatic MCP Server running on stdio');
18
- }
19
- main().catch((error) => {
20
- console.error('Fatal error:', error);
21
- process.exit(1);
22
- });
1
+ /**
2
+ * The library entry — importing this file has NO side effects.
3
+ *
4
+ * `bin.ts` is the executable; this is what a consumer imports. There are two
5
+ * such consumers: the hosted Streamable-HTTP transport in the platform's
6
+ * private `cloudflare/mcp`, and the VS Code extension
7
+ * (`integrations/vscode`), which bundles a stdio server into its `.vsix`.
8
+ * Both transports are converging on the same product — the complete toolset
9
+ * for authenticated callers, the anonymous deploy for everyone else and
10
+ * "one product, two transports" is only true if one of them can import the
11
+ * other.
12
+ *
13
+ * **The surface is exactly what a SECOND CONSUMER needs — nothing more.**
14
+ * That is the rule, and it is stricter than "curated". It read "a second
15
+ * TRANSPORT" until 1.0.0-beta.7, when the VS Code extension arrived as a
16
+ * consumer that is not a transport: it wants stdio's own composition,
17
+ * verbatim, running on the user's machine. The wording widened; the strictness
18
+ * did not.
19
+ *
20
+ * Every name below answers a question a consumer must otherwise answer for
21
+ * itself, and each admission was a restatement deleted, not a convenience
22
+ * added: `SERVER_NAME` and `UPLOAD_TOOL_NAME` were literals in two repos (the
23
+ * first also correlates the Apps-SDK widget to the connector), `PUBLIC_EXPIRY`
24
+ * was the same duration written out eight times, `DESCRIPTION_BLOCKS` the
25
+ * fragments two tool descriptions genuinely share, `ACCOUNT_TOOL_NAMES` is
26
+ * what lets the hosted catalogue fence name the fourteen without counting them
27
+ * again, and `createServer` deleted three regexes in another repo's build (see
28
+ * below).
29
+ *
30
+ * **`createServer` is exported; the configured `call` is not.** The extension
31
+ * previously reached stdio's composition by REGEX-PATCHING this package's
32
+ * compiled `dist/` at bundle time — stripping `bin`'s shebang, and rewriting
33
+ * the `createRequire(import.meta.url)('../package.json')` line inside
34
+ * `server.js` to inline a version literal. Three hacks against another
35
+ * package's build output, each of which the 1.x library split broke. A short
36
+ * entry point calling `createServer(ship, { version, via })` replaces all of
37
+ * them, which is a restatement deleted rather than a convenience added.
38
+ * `call` stays internal because a consumer configures its own hints through
39
+ * `createCall`, and stdio's instance is not a contract anyone needs.
40
+ *
41
+ * Its second argument is the HOST's own facts — the version it reports and the
42
+ * deploy origin its uploads carry — because a library has no manifest to read
43
+ * and no idea which product it was installed inside. A `startStdio` absorbing
44
+ * the transport as well was proposed and rejected; `CLAUDE.md` records why, and
45
+ * `tests/architecture/worker-safety.test.ts` is the fence that makes the reason
46
+ * mechanical rather than remembered.
47
+ *
48
+ * The old reason for withholding `createServer` — that its upload tool takes a
49
+ * filesystem PATH, a footgun to offer a Worker — is still true and is now the
50
+ * CALLER's judgement rather than an absence: `cloudflare/mcp` must keep
51
+ * authoring its own upload tool, and does. An absence cannot express "correct
52
+ * for one consumer, wrong for another"; a documented rule can. What makes the
53
+ * export safe to publish at all is that `createServer` takes its `version` as
54
+ * an ARGUMENT — so exporting it adds no `node:module` to the import graph of a
55
+ * module the Workers-hosted transport loads.
56
+ *
57
+ * `tests/index.test.ts` fences both directions — nothing missing, nothing
58
+ * extra — because adding an export is the quiet failure: everything published
59
+ * becomes a breaking change to remove.
60
+ */
61
+ export { createCall } from './call.js';
62
+ export { createServer } from './server.js';
63
+ export { ACCOUNT_TOOL_NAMES, registerAccountTools } from './tools.js';
64
+ export { ANNOTATIONS, DESCRIPTION_BLOCKS, INSTRUCTION_BLOCKS, PARAM_DESCRIPTIONS, PUBLIC_EXPIRY, SERVER_NAME, UPLOAD_TOOL_NAME, } from './vocabulary.js';
package/dist/server.d.ts CHANGED
@@ -1,3 +1,36 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type Ship from '@shipstatic/ship';
3
- export declare function createServer(ship: Ship): McpServer;
3
+ import { type DeploymentViaType } from '@shipstatic/types';
4
+ /**
5
+ * What the HOST knows about itself and this library must not assume.
6
+ *
7
+ * Both fields are the same category of fact, which is why they travel together
8
+ * rather than as a growing positional tail: a library has no manifest to read
9
+ * and no idea which product it was installed inside.
10
+ */
11
+ export interface ServerOptions {
12
+ /**
13
+ * The server's reported `serverInfo.version`. A parameter rather than
14
+ * something this module reads for itself: the executable knows its own
15
+ * package manifest, a library must not assume it has one, and reaching for
16
+ * `node:module` here would put a Node builtin in the import graph of a
17
+ * module the Workers-hosted transport also loads.
18
+ */
19
+ version: string;
20
+ /**
21
+ * The deploy origin this server's uploads are attributed to. Defaults to
22
+ * `mcp` — an npx install in some MCP client, which is what this package is
23
+ * on its own.
24
+ *
25
+ * It is a parameter because `via` names the DISTRIBUTION SURFACE, not the
26
+ * protocol: the GitHub Action reports `git` whatever invoked the workflow,
27
+ * and the web apps report `web`. The VS Code extension bundles this server
28
+ * into its `.vsix`, so its agent-mode deploys are the extension's — it
29
+ * passes `vsc`, and `mcp` goes back to meaning what it says.
30
+ */
31
+ via?: DeploymentViaType;
32
+ }
33
+ /**
34
+ * Builds the stdio server's full 15-tool surface over an injected client.
35
+ */
36
+ export declare function createServer(ship: Ship, options: ServerOptions): McpServer;