@myspec/mcp-server 0.1.0-next.9 → 0.1.0
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/dist/index.js +28 -21
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1086,6 +1086,7 @@ function transformSpecSessionResponse(raw) {
|
|
|
1086
1086
|
messageCount: raw.message_count,
|
|
1087
1087
|
tokenCount: raw.token_count,
|
|
1088
1088
|
context: raw.context,
|
|
1089
|
+
chatHistory: raw.chat_history,
|
|
1089
1090
|
startedAt: new Date(raw.started_at),
|
|
1090
1091
|
completedAt: raw.completed_at ? new Date(raw.completed_at) : void 0,
|
|
1091
1092
|
archivedAt: raw.archived_at ? new Date(raw.archived_at) : void 0,
|
|
@@ -1322,6 +1323,17 @@ var HttpFileClient = class {
|
|
|
1322
1323
|
expiresAt: new Date(response.expires_at)
|
|
1323
1324
|
};
|
|
1324
1325
|
}
|
|
1326
|
+
async getRevisionDownloadUrl(fileId, revisionNumber, jwtToken) {
|
|
1327
|
+
const response = await this.httpClient.get(
|
|
1328
|
+
`/project/v1/files/${fileId}/revisions/${revisionNumber}`,
|
|
1329
|
+
jwtToken,
|
|
1330
|
+
{ headers: { Accept: "application/json" } }
|
|
1331
|
+
);
|
|
1332
|
+
return {
|
|
1333
|
+
signedUrl: response.signed_url,
|
|
1334
|
+
expiresAt: new Date(response.expires_at)
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1325
1337
|
async downloadContent(fileId, jwtToken) {
|
|
1326
1338
|
const baseUrl = this.httpClient.getBaseUrl().replace(/\/$/, "");
|
|
1327
1339
|
const url = `${baseUrl}/project/v1/files/${fileId}`;
|
|
@@ -1519,6 +1531,7 @@ var HttpSpecSessionClient = class {
|
|
|
1519
1531
|
if (updates.messageCount !== void 0) body.message_count = updates.messageCount;
|
|
1520
1532
|
if (updates.tokenCount !== void 0) body.token_count = updates.tokenCount;
|
|
1521
1533
|
if (updates.context !== void 0) body.context = updates.context;
|
|
1534
|
+
if (updates.chatHistory !== void 0) body.chat_history = updates.chatHistory;
|
|
1522
1535
|
const raw = await this.httpClient.put(
|
|
1523
1536
|
`/project/v1/sessions/${sessionId}`,
|
|
1524
1537
|
body,
|
|
@@ -1615,6 +1628,11 @@ var PlatformClient = class {
|
|
|
1615
1628
|
async getFileDownloadUrl(fileId) {
|
|
1616
1629
|
return this.withTokenRetry((jwt) => this.file.getDownloadUrl(fileId, jwt));
|
|
1617
1630
|
}
|
|
1631
|
+
async getRevisionDownloadUrl(fileId, revisionNumber) {
|
|
1632
|
+
return this.withTokenRetry(
|
|
1633
|
+
(jwt) => this.file.getRevisionDownloadUrl(fileId, revisionNumber, jwt)
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1618
1636
|
async getAttachmentDownloadUrl(attachmentId) {
|
|
1619
1637
|
return this.withTokenRetry((jwt) => this.attachment.getDownloadUrl(attachmentId, jwt));
|
|
1620
1638
|
}
|
|
@@ -1769,12 +1787,12 @@ import { z as z2 } from "zod";
|
|
|
1769
1787
|
var inputSchema2 = {
|
|
1770
1788
|
file_id: z2.string().min(1).describe("UUID of the file"),
|
|
1771
1789
|
include_download_url: z2.number().int().nonnegative().optional().describe(
|
|
1772
|
-
"Revision number to include a download URL for.
|
|
1790
|
+
"Revision number to include a download URL for. Returns a signed, time-limited URL for that revision (latest or historical) that needs no credentials. Omit or 0 to skip."
|
|
1773
1791
|
)
|
|
1774
1792
|
};
|
|
1775
1793
|
var getFileTool = {
|
|
1776
1794
|
name: "get_file",
|
|
1777
|
-
description: "Get file metadata. With `include_download_url=N`, also returns a download URL for revision N
|
|
1795
|
+
description: "Get file metadata. With `include_download_url=N`, also returns a signed, time-limited download URL for revision N (latest or historical). The URL is self-authenticating, so no credentials are returned.",
|
|
1778
1796
|
inputSchema: inputSchema2,
|
|
1779
1797
|
handler: async (args, ctx) => {
|
|
1780
1798
|
const meta = await ctx.client.getFileMetadata(args.file_id);
|
|
@@ -1800,24 +1818,12 @@ var getFileTool = {
|
|
|
1800
1818
|
);
|
|
1801
1819
|
}
|
|
1802
1820
|
const isLatest = requested === meta.revisionCount;
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
expires_at: signed.expiresAt.toISOString()
|
|
1810
|
-
};
|
|
1811
|
-
} else {
|
|
1812
|
-
const url = `${ctx.client.baseUrl}/project/v1/files/${encodeURIComponent(meta.id)}/revisions/${String(requested)}`;
|
|
1813
|
-
const token = await ctx.client.getAccessTokenWithExpiry();
|
|
1814
|
-
downloadBlock = {
|
|
1815
|
-
download_url: url,
|
|
1816
|
-
download_revision: requested,
|
|
1817
|
-
expires_at: new Date(token.expiresAt).toISOString(),
|
|
1818
|
-
download_headers: [`Authorization: Bearer ${token.accessToken}`]
|
|
1819
|
-
};
|
|
1820
|
-
}
|
|
1821
|
+
const signed = isLatest ? await ctx.client.getFileDownloadUrl(meta.id) : await ctx.client.getRevisionDownloadUrl(meta.id, requested);
|
|
1822
|
+
const downloadBlock = {
|
|
1823
|
+
download_url: signed.signedUrl,
|
|
1824
|
+
download_revision: requested,
|
|
1825
|
+
expires_at: signed.expiresAt.toISOString()
|
|
1826
|
+
};
|
|
1821
1827
|
return jsonResult({ ...base, ...downloadBlock });
|
|
1822
1828
|
}
|
|
1823
1829
|
};
|
|
@@ -3377,7 +3383,8 @@ async function runOneConnection(opts) {
|
|
|
3377
3383
|
headers: {
|
|
3378
3384
|
Authorization: `Bearer ${opts.accessToken}`,
|
|
3379
3385
|
"X-Mcp-Client": `myspec-mcp-server/${opts.version}`,
|
|
3380
|
-
"X-Mcp-Root-Label": opts.rootLabel
|
|
3386
|
+
"X-Mcp-Root-Label": opts.rootLabel,
|
|
3387
|
+
"X-Client-Type": "mcp-server"
|
|
3381
3388
|
}
|
|
3382
3389
|
});
|
|
3383
3390
|
await waitForOpen(ws);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myspec/mcp-server",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "MySpec MCP server — exposes MySpec platform projects, files and attachments to MCP-aware clients via OAuth-authenticated access tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"typecheck": "tsc --noEmit",
|
|
24
24
|
"test": "vitest run",
|
|
25
25
|
"test:watch": "vitest",
|
|
26
|
+
"test:coverage": "vitest run --coverage",
|
|
27
|
+
"coverage:check": "npx tsx scripts/check-coverage.ts",
|
|
26
28
|
"test:integration": "npm run build && vitest run --config vitest.integration.config.ts",
|
|
27
29
|
"lint": "eslint src",
|
|
28
30
|
"lint:fix": "eslint src --fix",
|
|
@@ -52,6 +54,7 @@
|
|
|
52
54
|
"@myspec/shared": "file:../../packages/shared",
|
|
53
55
|
"@types/node": "^25.9.1",
|
|
54
56
|
"@types/ws": "^8.18.1",
|
|
57
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
55
58
|
"eslint": "^10.4.1",
|
|
56
59
|
"tsup": "^8.3.5",
|
|
57
60
|
"tsx": "^4.22.3",
|