@primate-intelligence/mcp 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/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # @primate-intelligence/mcp
2
+
3
+ MCP (Model Context Protocol) server for the [Primate Vision API](https://primateintelligence.ai/docs) by Primate Intelligence. Gives AI agents video scene understanding as tools: register a video, ask a question, get a deterministic answer with confidence and clip timestamps.
4
+
5
+ > **Status:** built in-repo. Not yet published to npm — run from the repo (`node mcp/dist/index.js`) until the first public release. A hosted SSE endpoint is planned.
6
+
7
+ ## Setup
8
+
9
+ ```jsonc
10
+ // claude_desktop_config.json / .mcp.json / mcp.json
11
+ {
12
+ "mcpServers": {
13
+ "primate-intelligence": {
14
+ "command": "npx",
15
+ "args": ["@primate-intelligence/mcp"],
16
+ "env": { "PRIMATE_API_KEY": "pv_live_…" }
17
+ }
18
+ }
19
+ }
20
+ ```
21
+
22
+ Get a free test key with no signup:
23
+
24
+ ```bash
25
+ curl -X POST https://api.primateintelligence.ai/v1/sandbox
26
+ ```
27
+
28
+ **Security contract:** the API key is read from the `PRIMATE_API_KEY` environment variable **only**. No tool accepts a key argument — keys never appear in agent transcripts (enforced by a unit test).
29
+
30
+ ## Tools (v1.0)
31
+
32
+ | Tool | Does |
33
+ |---|---|
34
+ | `create_video_from_url` | Register a video from a public https URL (`POST /v1/videos`) |
35
+ | `create_analysis` | Ask a question about a video (`POST /v1/analyses`) |
36
+ | `get_analysis` | Fetch analysis status/result (`GET /v1/analyses/{id}`) |
37
+ | `wait_for_analysis` | Poll until terminal state, return the final analysis |
38
+ | `list_models` | List available models (`GET /v1/models`) |
39
+ | `get_usage` | Credit balance + period meters (`GET /v1/usage`) |
40
+ | `get_test_fixture` | Stable fixture for integration self-verification (`GET /v1/test-fixture`) |
41
+
42
+ Tool descriptions and schemas mirror the OpenAPI document at `GET /v1/openapi.json` — the spec is the source of truth.
43
+
44
+ ## Typical agent flow
45
+
46
+ 1. `get_test_fixture` → verify the integration works (test keys return deterministic results)
47
+ 2. `create_video_from_url` with the customer's video URL
48
+ 3. `create_analysis` with a question ("Is there a person in this video?")
49
+ 4. `wait_for_analysis` → `result.answer` (`yes` | `no` | `indeterminate`) + `result.confidence` + `result.clips`
50
+ 5. On `insufficient_credits`: `get_usage`, report the balance, point the human at billing
51
+
52
+ ## Env
53
+
54
+ | Var | Required | Default |
55
+ |---|---|---|
56
+ | `PRIMATE_API_KEY` | yes | — |
57
+ | `PRIMATE_BASE_URL` | no | `https://api.primateintelligence.ai` |
package/dist/api.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Minimal API client for the MCP server.
3
+ *
4
+ * SECURITY (design §5.3 / §18.1): the API key is read from the
5
+ * PRIMATE_API_KEY environment variable ONLY. It is never accepted as a
6
+ * tool argument — that would land secret keys in agent transcripts.
7
+ */
8
+ export declare const BASE_URL: string;
9
+ export declare function apiKey(): string;
10
+ export interface ApiErrorBody {
11
+ code: string;
12
+ message: string;
13
+ docs_url?: string;
14
+ request_id?: string;
15
+ param?: string | null;
16
+ }
17
+ export declare class ApiError extends Error {
18
+ readonly status: number;
19
+ readonly body: ApiErrorBody;
20
+ constructor(status: number, body: ApiErrorBody);
21
+ }
22
+ export declare function api<T>(method: 'GET' | 'POST' | 'DELETE', path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
package/dist/api.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Minimal API client for the MCP server.
3
+ *
4
+ * SECURITY (design §5.3 / §18.1): the API key is read from the
5
+ * PRIMATE_API_KEY environment variable ONLY. It is never accepted as a
6
+ * tool argument — that would land secret keys in agent transcripts.
7
+ */
8
+ export const BASE_URL = (process.env.PRIMATE_BASE_URL ?? 'https://api.primateintelligence.ai').replace(/\/$/, '');
9
+ export function apiKey() {
10
+ const key = process.env.PRIMATE_API_KEY;
11
+ if (!key) {
12
+ throw new Error('PRIMATE_API_KEY is not set. Set it in the MCP server environment (never pass keys as tool arguments). ' +
13
+ 'Get a free test key: curl -X POST https://api.primateintelligence.ai/v1/sandbox');
14
+ }
15
+ return key;
16
+ }
17
+ export class ApiError extends Error {
18
+ status;
19
+ body;
20
+ constructor(status, body) {
21
+ super(`${body.code}: ${body.message}`);
22
+ this.status = status;
23
+ this.body = body;
24
+ }
25
+ }
26
+ export async function api(method, path, body, headers = {}) {
27
+ const res = await fetch(BASE_URL + path, {
28
+ method,
29
+ headers: {
30
+ Authorization: `Bearer ${apiKey()}`,
31
+ 'User-Agent': 'primate-intelligence-mcp/0.1.0',
32
+ ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
33
+ ...headers,
34
+ },
35
+ body: body !== undefined ? JSON.stringify(body) : undefined,
36
+ });
37
+ if (!res.ok) {
38
+ let err = { code: 'internal_error', message: `HTTP ${res.status}` };
39
+ try {
40
+ err = (await res.json()).error ?? err;
41
+ }
42
+ catch {
43
+ /* non-JSON */
44
+ }
45
+ throw new ApiError(res.status, err);
46
+ }
47
+ return (await res.json());
48
+ }
49
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,oCAAoC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAElH,MAAM,UAAU,MAAM;IACpB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,wGAAwG;YACtG,iFAAiF,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAUD,MAAM,OAAO,QAAS,SAAQ,KAAK;IACZ;IAAyB;IAA9C,YAAqB,MAAc,EAAW,IAAkB;QAC9D,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QADpB,WAAM,GAAN,MAAM,CAAQ;QAAW,SAAI,GAAJ,IAAI,CAAc;IAEhE,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,MAAiC,EACjC,IAAY,EACZ,IAAc,EACd,UAAkC,EAAE;IAEpC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,GAAG,IAAI,EAAE;QACvC,MAAM;QACN,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE;YACnC,YAAY,EAAE,gCAAgC;YAC9C,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,OAAO;SACX;QACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC5D,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,GAAG,GAAiB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QAClF,IAAI,CAAC;YACH,GAAG,GAAI,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6B,CAAC,KAAK,IAAI,GAAG,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;AACjC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @primate-intelligence/mcp — MCP server for the Primate Vision API.
3
+ *
4
+ * npx @primate-intelligence/mcp (stdio transport)
5
+ *
6
+ * Env:
7
+ * PRIMATE_API_KEY — required. Never passed as a tool argument (§5.3).
8
+ * PRIMATE_BASE_URL — optional override (default https://api.primateintelligence.ai).
9
+ *
10
+ * Docs: https://primateintelligence.ai/docs/agents
11
+ */
12
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
+ export declare function buildServer(): McpServer;
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @primate-intelligence/mcp — MCP server for the Primate Vision API.
4
+ *
5
+ * npx @primate-intelligence/mcp (stdio transport)
6
+ *
7
+ * Env:
8
+ * PRIMATE_API_KEY — required. Never passed as a tool argument (§5.3).
9
+ * PRIMATE_BASE_URL — optional override (default https://api.primateintelligence.ai).
10
+ *
11
+ * Docs: https://primateintelligence.ai/docs/agents
12
+ */
13
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
+ import { TOOLS, describeError } from './tools.js';
16
+ export function buildServer() {
17
+ const server = new McpServer({
18
+ name: 'primate-intelligence',
19
+ version: '0.1.0',
20
+ });
21
+ for (const tool of TOOLS) {
22
+ server.tool(tool.name, tool.description, tool.schema, async (args) => {
23
+ try {
24
+ const result = await tool.handler(args);
25
+ return {
26
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
27
+ };
28
+ }
29
+ catch (e) {
30
+ return {
31
+ isError: true,
32
+ content: [{ type: 'text', text: describeError(e) }],
33
+ };
34
+ }
35
+ });
36
+ }
37
+ return server;
38
+ }
39
+ async function main() {
40
+ // Fail fast with a helpful message when the env contract is unmet.
41
+ if (!process.env.PRIMATE_API_KEY) {
42
+ console.error('PRIMATE_API_KEY is not set. Add it to the MCP server env, e.g.\n' +
43
+ ' { "mcpServers": { "primate-intelligence": { "command": "npx", "args": ["@primate-intelligence/mcp"], "env": { "PRIMATE_API_KEY": "pv_…" } } } }\n' +
44
+ 'Get a free test key: curl -X POST https://api.primateintelligence.ai/v1/sandbox');
45
+ process.exit(1);
46
+ }
47
+ const server = buildServer();
48
+ await server.connect(new StdioServerTransport());
49
+ console.error('primate-intelligence MCP server running (stdio)');
50
+ }
51
+ // Only run when executed directly (not when imported by tests).
52
+ const invokedDirectly = process.argv[1]?.endsWith('index.js') || process.argv[1]?.endsWith('index.ts');
53
+ if (invokedDirectly) {
54
+ main().catch((e) => {
55
+ console.error(e);
56
+ process.exit(1);
57
+ });
58
+ }
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;YAC5F,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAa,CAAC,CAAC;gBACjD,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;iBAC5E,CAAC;YACJ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC7D,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,mEAAmE;IACnE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CACX,kEAAkE;YAChE,qJAAqJ;YACrJ,iFAAiF,CACpF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACnE,CAAC;AAED,gEAAgE;AAChE,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;AACvG,IAAI,eAAe,EAAE,CAAC;IACpB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Tool definitions for @primate-intelligence/mcp (design §5, PRI-438 P9).
3
+ *
4
+ * Tool descriptions and schemas mirror the OpenAPI document served at
5
+ * GET /v1/openapi.json — the spec is the source of truth. v1.0 scope:
6
+ * create_video_from_url, create_analysis, get_analysis,
7
+ * wait_for_analysis, list_models, get_usage, get_test_fixture.
8
+ *
9
+ * SECURITY: PRIMATE_API_KEY comes from the environment only — no tool
10
+ * accepts a key argument (§5.3: prevents keys landing in transcripts).
11
+ */
12
+ import { z } from 'zod';
13
+ export interface ToolDef<Shape extends z.ZodRawShape = z.ZodRawShape> {
14
+ name: string;
15
+ description: string;
16
+ schema: Shape;
17
+ handler: (args: z.objectOutputType<Shape, z.ZodTypeAny>) => Promise<unknown>;
18
+ }
19
+ /** Format API errors so agents can self-correct (code + docs_url + retryability). */
20
+ export declare function describeError(e: unknown): string;
21
+ export declare const TOOLS: ToolDef[];
package/dist/tools.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Tool definitions for @primate-intelligence/mcp (design §5, PRI-438 P9).
3
+ *
4
+ * Tool descriptions and schemas mirror the OpenAPI document served at
5
+ * GET /v1/openapi.json — the spec is the source of truth. v1.0 scope:
6
+ * create_video_from_url, create_analysis, get_analysis,
7
+ * wait_for_analysis, list_models, get_usage, get_test_fixture.
8
+ *
9
+ * SECURITY: PRIMATE_API_KEY comes from the environment only — no tool
10
+ * accepts a key argument (§5.3: prevents keys landing in transcripts).
11
+ */
12
+ import { z } from 'zod';
13
+ import { api, ApiError } from './api.js';
14
+ /** Format API errors so agents can self-correct (code + docs_url + retryability). */
15
+ export function describeError(e) {
16
+ if (e instanceof ApiError) {
17
+ const parts = [
18
+ `API error ${e.body.code} (HTTP ${e.status}): ${e.body.message}`,
19
+ e.body.docs_url ? `Docs: ${e.body.docs_url}` : '',
20
+ e.body.request_id ? `request_id: ${e.body.request_id}` : '',
21
+ ];
22
+ return parts.filter(Boolean).join('\n');
23
+ }
24
+ return e instanceof Error ? e.message : String(e);
25
+ }
26
+ const TERMINAL = new Set(['completed', 'failed', 'canceled']);
27
+ export const TOOLS = [
28
+ {
29
+ name: 'create_video_from_url',
30
+ description: 'Register a video from a public https URL for analysis (POST /v1/videos, URL-ingest mode). ' +
31
+ 'The API fetches the video asynchronously — the returned video starts in status "processing" and becomes "ready". ' +
32
+ 'Supports video/mp4 and video/quicktime, max 2 GiB. Returns the video resource with its id (video_…).',
33
+ schema: {
34
+ url: z.string().url().describe('Public https URL of the video to ingest (https only, port 443).'),
35
+ metadata: z.record(z.string()).optional().describe('Optional key-value metadata to attach.'),
36
+ },
37
+ handler: (args) => api('POST', '/v1/videos', { url: args.url, metadata: args.metadata }),
38
+ },
39
+ {
40
+ name: 'create_analysis',
41
+ description: 'Ask a question about a video (POST /v1/analyses). Provide video_id (video_…) and a free-text prompt like ' +
42
+ '"Is there a person in this video?". Analysis runs asynchronously — use wait_for_analysis to block until done. ' +
43
+ 'The result contains answer (yes|no|indeterminate), confidence (0-1), and clip timestamps.',
44
+ schema: {
45
+ video_id: z.string().describe('The video to analyze (video_… id from create_video_from_url).'),
46
+ prompt: z.string().max(2000).describe('Free-text question about the video, e.g. "Is there a person in this video?"'),
47
+ model: z.string().optional().describe('Model id (see list_models). Defaults to the current default model.'),
48
+ metadata: z.record(z.string()).optional().describe('Optional key-value metadata to attach.'),
49
+ },
50
+ handler: (args) => api('POST', '/v1/analyses', {
51
+ video_id: args.video_id,
52
+ prompt: args.prompt,
53
+ model: args.model,
54
+ metadata: args.metadata,
55
+ }),
56
+ },
57
+ {
58
+ name: 'get_analysis',
59
+ description: 'Fetch an analysis by id (GET /v1/analyses/{id}). While running, shows live progress and queue_position. ' +
60
+ 'When status is "completed", result carries answer/confidence/clips.',
61
+ schema: {
62
+ analysis_id: z.string().describe('The analysis id (an_…).'),
63
+ },
64
+ handler: (args) => api('GET', `/v1/analyses/${args.analysis_id}`),
65
+ },
66
+ {
67
+ name: 'wait_for_analysis',
68
+ description: 'Block until an analysis reaches a terminal state (completed | failed | canceled), polling GET /v1/analyses/{id}. ' +
69
+ 'Returns the final analysis. Default timeout 120s (test-mode analyses complete in seconds).',
70
+ schema: {
71
+ analysis_id: z.string().describe('The analysis id (an_…).'),
72
+ timeout_s: z.number().int().min(1).max(600).optional().describe('Max seconds to wait (default 120).'),
73
+ },
74
+ handler: async (args) => {
75
+ const timeoutMs = (args.timeout_s ?? 120) * 1000;
76
+ const deadline = Date.now() + timeoutMs;
77
+ let analysis = await api('GET', `/v1/analyses/${args.analysis_id}`);
78
+ while (!TERMINAL.has(analysis.status)) {
79
+ if (Date.now() > deadline) {
80
+ return {
81
+ ...analysis,
82
+ _mcp_note: `Timed out after ${args.timeout_s ?? 120}s — analysis is still ${analysis.status}. Call wait_for_analysis again or get_analysis later.`,
83
+ };
84
+ }
85
+ await new Promise((r) => setTimeout(r, 2000));
86
+ analysis = await api('GET', `/v1/analyses/${args.analysis_id}`);
87
+ }
88
+ return analysis;
89
+ },
90
+ },
91
+ {
92
+ name: 'list_models',
93
+ description: 'List available analysis models (GET /v1/models) with status (stable | preview | deprecated) and capabilities. ' +
94
+ 'Use the model marked default:true unless you have a reason not to.',
95
+ schema: {},
96
+ handler: () => api('GET', '/v1/models'),
97
+ },
98
+ {
99
+ name: 'get_usage',
100
+ description: 'Get credit balance and period usage meters for the current API key (GET /v1/usage). ' +
101
+ 'Use this after an insufficient_credits error to report the balance.',
102
+ schema: {},
103
+ handler: () => api('GET', '/v1/usage'),
104
+ },
105
+ {
106
+ name: 'get_test_fixture',
107
+ description: 'Get the stable test fixture (GET /v1/test-fixture): a video URL + prompt + expected answer for verifying an ' +
108
+ 'integration end-to-end without burning quota. Test-mode (pv_test_) keys return deterministic canned results.',
109
+ schema: {},
110
+ handler: () => api('GET', '/v1/test-fixture'),
111
+ },
112
+ ];
113
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@primate-intelligence/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for the Primate Vision API (Primate Intelligence) — video scene understanding tools for AI agents.",
5
+ "license": "MIT",
6
+ "author": "Primate Intelligence",
7
+ "homepage": "https://primateintelligence.ai/docs/agents",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Primate-Intelligence/primate-intelligence-api.git",
11
+ "directory": "mcp"
12
+ },
13
+ "keywords": [
14
+ "mcp",
15
+ "modelcontextprotocol",
16
+ "video",
17
+ "vision",
18
+ "ai",
19
+ "primate-intelligence"
20
+ ],
21
+ "type": "module",
22
+ "bin": {
23
+ "primate-intelligence-mcp": "./dist/index.js"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc && node -e \"const fs=require('fs');const p='dist/index.js';fs.writeFileSync(p,'#!/usr/bin/env node\\n'+fs.readFileSync(p,'utf8'));fs.chmodSync(p,0o755)\"",
35
+ "test": "vitest run",
36
+ "prepack": "npm run build"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.12.0",
40
+ "zod": "^3.23.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^22.20.1",
44
+ "typescript": "^5.6.0",
45
+ "vitest": "^2.1.0"
46
+ }
47
+ }