@inferencesh/sdk 0.6.8 → 0.6.12

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +70 -1
  3. package/dist/agent/actions.js +3 -3
  4. package/dist/agent/actions.test.js +89 -0
  5. package/dist/agent/api.test.js +86 -8
  6. package/dist/api/agents.d.ts +10 -0
  7. package/dist/api/agents.js +17 -3
  8. package/dist/api/agents.test.js +303 -92
  9. package/dist/api/api-keys.d.ts +24 -0
  10. package/dist/api/api-keys.js +26 -0
  11. package/dist/api/api-keys.test.d.ts +1 -0
  12. package/dist/api/api-keys.test.js +44 -0
  13. package/dist/api/apps.js +1 -1
  14. package/dist/api/apps.test.d.ts +1 -0
  15. package/dist/api/apps.test.js +135 -0
  16. package/dist/api/chats.d.ts +14 -0
  17. package/dist/api/chats.js +18 -0
  18. package/dist/api/chats.test.d.ts +1 -0
  19. package/dist/api/chats.test.js +85 -0
  20. package/dist/api/engines.d.ts +12 -0
  21. package/dist/api/engines.js +18 -0
  22. package/dist/api/engines.test.d.ts +1 -0
  23. package/dist/api/engines.test.js +133 -0
  24. package/dist/api/files.test.js +186 -6
  25. package/dist/api/flow-runs.test.d.ts +1 -0
  26. package/dist/api/flow-runs.test.js +97 -0
  27. package/dist/api/flows.d.ts +4 -0
  28. package/dist/api/flows.js +6 -0
  29. package/dist/api/flows.test.d.ts +1 -0
  30. package/dist/api/flows.test.js +118 -0
  31. package/dist/api/integrations.d.ts +41 -0
  32. package/dist/api/integrations.js +56 -0
  33. package/dist/api/integrations.test.d.ts +1 -0
  34. package/dist/api/integrations.test.js +109 -0
  35. package/dist/api/knowledge.d.ts +112 -0
  36. package/dist/api/knowledge.js +163 -0
  37. package/dist/api/knowledge.test.d.ts +1 -0
  38. package/dist/api/knowledge.test.js +94 -0
  39. package/dist/api/mcp-servers.d.ts +45 -0
  40. package/dist/api/mcp-servers.js +62 -0
  41. package/dist/api/mcp-servers.test.d.ts +1 -0
  42. package/dist/api/mcp-servers.test.js +64 -0
  43. package/dist/api/projects.d.ts +29 -0
  44. package/dist/api/projects.js +38 -0
  45. package/dist/api/projects.test.d.ts +1 -0
  46. package/dist/api/projects.test.js +52 -0
  47. package/dist/api/search.d.ts +21 -0
  48. package/dist/api/search.js +20 -0
  49. package/dist/api/search.test.d.ts +1 -0
  50. package/dist/api/search.test.js +39 -0
  51. package/dist/api/secrets.d.ts +29 -0
  52. package/dist/api/secrets.js +38 -0
  53. package/dist/api/secrets.test.d.ts +1 -0
  54. package/dist/api/secrets.test.js +61 -0
  55. package/dist/api/sessions.test.js +4 -4
  56. package/dist/api/tasks.d.ts +13 -1
  57. package/dist/api/tasks.js +18 -0
  58. package/dist/api/tasks.test.js +174 -22
  59. package/dist/api/teams.d.ts +71 -0
  60. package/dist/api/teams.js +92 -0
  61. package/dist/api/teams.test.d.ts +1 -0
  62. package/dist/api/teams.test.js +79 -0
  63. package/dist/client.test.js +8 -8
  64. package/dist/http/client.d.ts +5 -0
  65. package/dist/http/client.js +46 -48
  66. package/dist/http/client.test.js +296 -13
  67. package/dist/http/errors.test.js +13 -0
  68. package/dist/index.d.ts +25 -0
  69. package/dist/index.js +25 -0
  70. package/dist/proxy/express.test.d.ts +1 -0
  71. package/dist/proxy/express.test.js +106 -0
  72. package/dist/proxy/index.test.js +10 -1
  73. package/dist/tool-builder.test.js +11 -1
  74. package/dist/types.d.ts +793 -23
  75. package/dist/types.js +180 -8
  76. package/package.json +4 -4
@@ -0,0 +1,109 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { IntegrationsAPI } from './integrations';
3
+ import { IntegrationProviderGoogleSA } from '../types';
4
+ const mockFetch = jest.fn();
5
+ global.fetch = mockFetch;
6
+ function mockJsonResponse(body) {
7
+ mockFetch.mockResolvedValueOnce({
8
+ ok: true,
9
+ status: 200,
10
+ text: () => Promise.resolve(JSON.stringify(body)),
11
+ });
12
+ }
13
+ describe('IntegrationsAPI', () => {
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ });
17
+ const api = () => new IntegrationsAPI(new HttpClient({ apiKey: 'test-key' }));
18
+ it('should POST /integrations/list for list()', async () => {
19
+ const page = { items: [{ provider: 'slack' }], next_cursor: null };
20
+ mockJsonResponse(page);
21
+ const result = await api().list();
22
+ expect(result).toEqual(page);
23
+ const [url, init] = mockFetch.mock.calls[0];
24
+ expect(url).toContain('/integrations/list');
25
+ expect(init.method).toBe('POST');
26
+ });
27
+ it('should GET /integrations/available for listAvailable()', async () => {
28
+ const available = [{ provider: 'github' }];
29
+ mockJsonResponse(available);
30
+ const result = await api().listAvailable();
31
+ expect(result).toEqual(available);
32
+ const [url, init] = mockFetch.mock.calls[0];
33
+ expect(url).toContain('/integrations/available');
34
+ expect(init.method).toBe('GET');
35
+ });
36
+ it('should POST /integrations for connect()', async () => {
37
+ const payload = { provider: 'slack', config: { token: 'xoxb-123' } };
38
+ const response = { integration: { provider: 'slack' }, redirect_url: null };
39
+ mockJsonResponse(response);
40
+ const result = await api().connect(payload);
41
+ expect(result).toEqual(response);
42
+ const [url, init] = mockFetch.mock.calls[0];
43
+ expect(url).toContain('/integrations');
44
+ expect(init.method).toBe('POST');
45
+ expect(JSON.parse(init.body)).toEqual(payload);
46
+ });
47
+ it('should GET /integrations/{provider} for get()', async () => {
48
+ const integration = { provider: 'slack', status: 'connected' };
49
+ mockJsonResponse(integration);
50
+ const result = await api().get('slack');
51
+ expect(result).toEqual(integration);
52
+ const [url, init] = mockFetch.mock.calls[0];
53
+ expect(url).toContain('/integrations/slack');
54
+ expect(init.method).toBe('GET');
55
+ });
56
+ it('should DELETE /integrations/{provider} for disconnect()', async () => {
57
+ mockJsonResponse(null);
58
+ await api().disconnect('slack');
59
+ const [url, init] = mockFetch.mock.calls[0];
60
+ expect(url).toContain('/integrations/slack');
61
+ expect(init.method).toBe('DELETE');
62
+ });
63
+ it('should GET /integrations/configs for getConfigs()', async () => {
64
+ const configs = [{ provider: 'github', scopes: ['repo'] }];
65
+ mockJsonResponse(configs);
66
+ const result = await api().getConfigs();
67
+ expect(result).toEqual(configs);
68
+ const [url, init] = mockFetch.mock.calls[0];
69
+ expect(url).toContain('/integrations/configs');
70
+ expect(init.method).toBe('GET');
71
+ });
72
+ it('should GET /integrations/capabilities for getCapabilities()', async () => {
73
+ const capabilities = { slack: ['post_message'] };
74
+ mockJsonResponse(capabilities);
75
+ const result = await api().getCapabilities();
76
+ expect(result).toEqual(capabilities);
77
+ const [url, init] = mockFetch.mock.calls[0];
78
+ expect(url).toContain('/integrations/capabilities');
79
+ expect(init.method).toBe('GET');
80
+ });
81
+ it('should POST typed integration requirements with secrets and scopes for checkRequirements()', async () => {
82
+ const payload = {
83
+ integrations: [
84
+ {
85
+ key: IntegrationProviderGoogleSA,
86
+ secrets: ['GOOGLE_SA_JSON'],
87
+ scopes: ['https://www.googleapis.com/auth/calendar'],
88
+ },
89
+ ],
90
+ };
91
+ const response = {
92
+ satisfied: false,
93
+ errors: [
94
+ {
95
+ type: 'scope',
96
+ message: 'Missing calendar scope',
97
+ action: { type: 'add_scopes', provider: IntegrationProviderGoogleSA, scopes: ['https://www.googleapis.com/auth/calendar'] },
98
+ },
99
+ ],
100
+ };
101
+ mockJsonResponse(response);
102
+ const result = await api().checkRequirements(payload);
103
+ expect(result).toEqual(response);
104
+ const [url, init] = mockFetch.mock.calls[0];
105
+ expect(url).toContain('/integrations/check');
106
+ expect(init.method).toBe('POST');
107
+ expect(JSON.parse(init.body)).toEqual(payload);
108
+ });
109
+ });
@@ -0,0 +1,112 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { KnowledgeDTO, KnowledgeVersionDTO, KnowledgeCreateRequest, SkillDTO, SkillVersionDTO, CursorListRequest, CursorListResponse, PublicSkillStoreDTO } from '../types';
3
+ /**
4
+ * Knowledge API
5
+ */
6
+ export declare class KnowledgeAPI {
7
+ private readonly http;
8
+ constructor(http: HttpClient);
9
+ /**
10
+ * List knowledge entries with cursor-based pagination
11
+ */
12
+ list(params?: Partial<CursorListRequest>): Promise<CursorListResponse<KnowledgeDTO>>;
13
+ /**
14
+ * Get a knowledge entry by ID
15
+ */
16
+ get(id: string): Promise<KnowledgeDTO>;
17
+ /**
18
+ * Get a knowledge entry by namespace/name
19
+ */
20
+ getByName(namespace: string, name: string): Promise<KnowledgeDTO>;
21
+ /**
22
+ * Create a knowledge entry
23
+ */
24
+ create(data: KnowledgeCreateRequest): Promise<KnowledgeDTO>;
25
+ /**
26
+ * Update a knowledge entry
27
+ */
28
+ update(id: string, data: Partial<KnowledgeDTO>): Promise<KnowledgeDTO>;
29
+ /**
30
+ * Delete a knowledge entry
31
+ */
32
+ delete(id: string): Promise<void>;
33
+ /**
34
+ * List knowledge versions
35
+ */
36
+ listVersions(id: string, params?: Partial<CursorListRequest>): Promise<CursorListResponse<KnowledgeVersionDTO>>;
37
+ /**
38
+ * Get a specific version
39
+ */
40
+ getVersion(id: string, versionId: string): Promise<KnowledgeVersionDTO>;
41
+ /**
42
+ * Transfer ownership
43
+ */
44
+ transferOwnership(id: string, newTeamId: string): Promise<KnowledgeDTO>;
45
+ /**
46
+ * Update visibility
47
+ */
48
+ updateVisibility(id: string, visibility: string): Promise<KnowledgeDTO>;
49
+ }
50
+ /**
51
+ * Skills API
52
+ */
53
+ export declare class SkillsAPI {
54
+ private readonly http;
55
+ constructor(http: HttpClient);
56
+ /**
57
+ * List skills with cursor-based pagination
58
+ */
59
+ list(params?: Partial<CursorListRequest>): Promise<CursorListResponse<SkillDTO>>;
60
+ /**
61
+ * Get a skill by ID
62
+ */
63
+ get(id: string): Promise<SkillDTO>;
64
+ /**
65
+ * Get a skill by namespace/name
66
+ */
67
+ getByName(namespace: string, name: string): Promise<SkillDTO>;
68
+ /**
69
+ * Resolve a skill (store + GitHub fallback)
70
+ */
71
+ resolve(ref: string, skill?: string): Promise<unknown>;
72
+ /**
73
+ * Create/publish a skill
74
+ */
75
+ create(data: Partial<SkillDTO>): Promise<SkillDTO>;
76
+ /**
77
+ * Update a skill
78
+ */
79
+ update(id: string, data: Partial<SkillDTO>): Promise<SkillDTO>;
80
+ /**
81
+ * Delete a skill
82
+ */
83
+ delete(id: string): Promise<void>;
84
+ /**
85
+ * List skill versions
86
+ */
87
+ listVersions(id: string, params?: Partial<CursorListRequest>): Promise<CursorListResponse<SkillVersionDTO>>;
88
+ /**
89
+ * Get a specific skill version
90
+ */
91
+ getVersion(id: string, versionId: string): Promise<SkillVersionDTO>;
92
+ /**
93
+ * Download a skill
94
+ */
95
+ download(namespace: string, name: string): Promise<unknown>;
96
+ /**
97
+ * Get skill content
98
+ */
99
+ getContent(namespace: string, name: string): Promise<unknown>;
100
+ /**
101
+ * Transfer ownership
102
+ */
103
+ transferOwnership(id: string, newTeamId: string): Promise<SkillDTO>;
104
+ /**
105
+ * Update visibility
106
+ */
107
+ updateVisibility(id: string, visibility: string): Promise<SkillDTO>;
108
+ /**
109
+ * List skills in the public store
110
+ */
111
+ listStore(params?: Partial<CursorListRequest>): Promise<CursorListResponse<PublicSkillStoreDTO>>;
112
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Knowledge API
3
+ */
4
+ export class KnowledgeAPI {
5
+ constructor(http) {
6
+ this.http = http;
7
+ }
8
+ /**
9
+ * List knowledge entries with cursor-based pagination
10
+ */
11
+ async list(params) {
12
+ return this.http.request('post', '/knowledge/list', { data: params });
13
+ }
14
+ /**
15
+ * Get a knowledge entry by ID
16
+ */
17
+ async get(id) {
18
+ return this.http.request('get', `/knowledge/${id}`);
19
+ }
20
+ /**
21
+ * Get a knowledge entry by namespace/name
22
+ */
23
+ async getByName(namespace, name) {
24
+ return this.http.request('get', `/knowledge/${namespace}/${name}`);
25
+ }
26
+ /**
27
+ * Create a knowledge entry
28
+ */
29
+ async create(data) {
30
+ return this.http.request('post', '/knowledge', { data });
31
+ }
32
+ /**
33
+ * Update a knowledge entry
34
+ */
35
+ async update(id, data) {
36
+ return this.http.request('post', `/knowledge/${id}`, { data });
37
+ }
38
+ /**
39
+ * Delete a knowledge entry
40
+ */
41
+ async delete(id) {
42
+ return this.http.request('delete', `/knowledge/${id}`);
43
+ }
44
+ /**
45
+ * List knowledge versions
46
+ */
47
+ async listVersions(id, params) {
48
+ return this.http.request('post', `/knowledge/${id}/versions/list`, { data: params });
49
+ }
50
+ /**
51
+ * Get a specific version
52
+ */
53
+ async getVersion(id, versionId) {
54
+ return this.http.request('get', `/knowledge/${id}/versions/${versionId}`);
55
+ }
56
+ /**
57
+ * Transfer ownership
58
+ */
59
+ async transferOwnership(id, newTeamId) {
60
+ return this.http.request('post', `/knowledge/${id}/transfer`, { data: { team_id: newTeamId } });
61
+ }
62
+ /**
63
+ * Update visibility
64
+ */
65
+ async updateVisibility(id, visibility) {
66
+ return this.http.request('post', `/knowledge/${id}/visibility`, { data: { visibility } });
67
+ }
68
+ }
69
+ /**
70
+ * Skills API
71
+ */
72
+ export class SkillsAPI {
73
+ constructor(http) {
74
+ this.http = http;
75
+ }
76
+ /**
77
+ * List skills with cursor-based pagination
78
+ */
79
+ async list(params) {
80
+ return this.http.request('post', '/skills/list', { data: params });
81
+ }
82
+ /**
83
+ * Get a skill by ID
84
+ */
85
+ async get(id) {
86
+ return this.http.request('get', `/skills/${id}`);
87
+ }
88
+ /**
89
+ * Get a skill by namespace/name
90
+ */
91
+ async getByName(namespace, name) {
92
+ return this.http.request('get', `/skills/${namespace}/${name}`);
93
+ }
94
+ /**
95
+ * Resolve a skill (store + GitHub fallback)
96
+ */
97
+ async resolve(ref, skill) {
98
+ const params = { ref };
99
+ if (skill)
100
+ params.skill = skill;
101
+ return this.http.request('get', '/skills/resolve', { params });
102
+ }
103
+ /**
104
+ * Create/publish a skill
105
+ */
106
+ async create(data) {
107
+ return this.http.request('post', '/skills', { data });
108
+ }
109
+ /**
110
+ * Update a skill
111
+ */
112
+ async update(id, data) {
113
+ return this.http.request('post', `/skills/${id}`, { data });
114
+ }
115
+ /**
116
+ * Delete a skill
117
+ */
118
+ async delete(id) {
119
+ return this.http.request('delete', `/skills/${id}`);
120
+ }
121
+ /**
122
+ * List skill versions
123
+ */
124
+ async listVersions(id, params) {
125
+ return this.http.request('post', `/skills/${id}/versions/list`, { data: params });
126
+ }
127
+ /**
128
+ * Get a specific skill version
129
+ */
130
+ async getVersion(id, versionId) {
131
+ return this.http.request('get', `/skills/${id}/versions/${versionId}`);
132
+ }
133
+ /**
134
+ * Download a skill
135
+ */
136
+ async download(namespace, name) {
137
+ return this.http.request('get', `/skills/${namespace}/${name}/download`);
138
+ }
139
+ /**
140
+ * Get skill content
141
+ */
142
+ async getContent(namespace, name) {
143
+ return this.http.request('get', `/skills/${namespace}/${name}/content`);
144
+ }
145
+ /**
146
+ * Transfer ownership
147
+ */
148
+ async transferOwnership(id, newTeamId) {
149
+ return this.http.request('post', `/skills/${id}/transfer`, { data: { team_id: newTeamId } });
150
+ }
151
+ /**
152
+ * Update visibility
153
+ */
154
+ async updateVisibility(id, visibility) {
155
+ return this.http.request('post', `/skills/${id}/visibility`, { data: { visibility } });
156
+ }
157
+ /**
158
+ * List skills in the public store
159
+ */
160
+ async listStore(params) {
161
+ return this.http.request('post', '/store/skills/list', { data: params });
162
+ }
163
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,94 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { KnowledgeAPI, SkillsAPI } from './knowledge';
3
+ const mockFetch = jest.fn();
4
+ global.fetch = mockFetch;
5
+ function mockJsonResponse(body) {
6
+ mockFetch.mockResolvedValueOnce({
7
+ ok: true,
8
+ status: 200,
9
+ text: () => Promise.resolve(JSON.stringify(body)),
10
+ });
11
+ }
12
+ describe('KnowledgeAPI', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ const api = () => new KnowledgeAPI(new HttpClient({ apiKey: 'test-key' }));
17
+ it('should POST /knowledge/list for list()', async () => {
18
+ const page = { items: [{ id: 'know-1' }], next_cursor: null };
19
+ mockJsonResponse(page);
20
+ const result = await api().list();
21
+ expect(result).toEqual(page);
22
+ const [url, init] = mockFetch.mock.calls[0];
23
+ expect(url).toContain('/knowledge/list');
24
+ expect(init.method).toBe('POST');
25
+ });
26
+ it('should GET /knowledge/{namespace}/{name} for getByName()', async () => {
27
+ const entry = { id: 'know-1', namespace: 'acme', name: 'docs' };
28
+ mockJsonResponse(entry);
29
+ const result = await api().getByName('acme', 'docs');
30
+ expect(result).toEqual(entry);
31
+ const [url, init] = mockFetch.mock.calls[0];
32
+ expect(url).toContain('/knowledge/acme/docs');
33
+ expect(init.method).toBe('GET');
34
+ });
35
+ it('should POST /knowledge for create()', async () => {
36
+ const payload = { namespace: 'acme', name: 'docs', content: 'hello' };
37
+ const entry = { id: 'know-new', ...payload };
38
+ mockJsonResponse(entry);
39
+ const result = await api().create(payload);
40
+ expect(result).toEqual(entry);
41
+ const [url, init] = mockFetch.mock.calls[0];
42
+ expect(url).toContain('/knowledge');
43
+ expect(init.method).toBe('POST');
44
+ });
45
+ it('should POST team_id for transferOwnership()', async () => {
46
+ const entry = { id: 'know-1' };
47
+ mockJsonResponse(entry);
48
+ await api().transferOwnership('know-1', 'team-5');
49
+ const [url, init] = mockFetch.mock.calls[0];
50
+ expect(url).toContain('/knowledge/know-1/transfer');
51
+ expect(JSON.parse(init.body)).toEqual({ team_id: 'team-5' });
52
+ });
53
+ });
54
+ describe('SkillsAPI', () => {
55
+ beforeEach(() => {
56
+ jest.clearAllMocks();
57
+ });
58
+ const api = () => new SkillsAPI(new HttpClient({ apiKey: 'test-key' }));
59
+ it('should GET /skills/resolve with ref param for resolve()', async () => {
60
+ const resolved = { ref: 'acme/skill@v1', content: '{}' };
61
+ mockJsonResponse(resolved);
62
+ const result = await api().resolve('acme/skill@v1', 'main');
63
+ expect(result).toEqual(resolved);
64
+ const [url] = mockFetch.mock.calls[0];
65
+ expect(url).toContain('/skills/resolve');
66
+ expect(url).toContain('ref=acme');
67
+ expect(url).toContain('skill=main');
68
+ });
69
+ it('should GET /skills/{namespace}/{name} for getByName()', async () => {
70
+ const skill = { id: 'skill-1', namespace: 'acme', name: 'research' };
71
+ mockJsonResponse(skill);
72
+ const result = await api().getByName('acme', 'research');
73
+ expect(result).toEqual(skill);
74
+ const [url, init] = mockFetch.mock.calls[0];
75
+ expect(url).toContain('/skills/acme/research');
76
+ expect(init.method).toBe('GET');
77
+ });
78
+ it('should GET /skills/{namespace}/{name}/download for download()', async () => {
79
+ mockJsonResponse({ url: 'https://cdn.example.com/skill.zip' });
80
+ await api().download('acme', 'research');
81
+ const [url, init] = mockFetch.mock.calls[0];
82
+ expect(url).toContain('/skills/acme/research/download');
83
+ expect(init.method).toBe('GET');
84
+ });
85
+ it('should POST /store/skills/list for listStore()', async () => {
86
+ const page = { items: [{ namespace: 'public', name: 'starter' }], next_cursor: null };
87
+ mockJsonResponse(page);
88
+ const result = await api().listStore();
89
+ expect(result).toEqual(page);
90
+ const [url, init] = mockFetch.mock.calls[0];
91
+ expect(url).toContain('/store/skills/list');
92
+ expect(init.method).toBe('POST');
93
+ });
94
+ });
@@ -0,0 +1,45 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { MCPServerDTO, CursorListRequest, CursorListResponse } from '../types';
3
+ /**
4
+ * MCP Servers API
5
+ */
6
+ export declare class MCPServersAPI {
7
+ private readonly http;
8
+ constructor(http: HttpClient);
9
+ /**
10
+ * List public MCP servers
11
+ */
12
+ list(params?: Partial<CursorListRequest>): Promise<CursorListResponse<MCPServerDTO>>;
13
+ /**
14
+ * Get an MCP server by slug
15
+ */
16
+ get(slug: string): Promise<MCPServerDTO>;
17
+ /**
18
+ * List tools for an MCP server
19
+ */
20
+ listTools(slug: string): Promise<unknown[]>;
21
+ /**
22
+ * Call a tool on an MCP server
23
+ */
24
+ callTool(slug: string, tool: string, input: unknown): Promise<unknown>;
25
+ /**
26
+ * List user's own MCP servers
27
+ */
28
+ listOwned(params?: Partial<CursorListRequest>): Promise<CursorListResponse<MCPServerDTO>>;
29
+ /**
30
+ * Get a user's MCP server by ID
31
+ */
32
+ getOwned(id: string): Promise<MCPServerDTO>;
33
+ /**
34
+ * Create an MCP server
35
+ */
36
+ create(data: Partial<MCPServerDTO>): Promise<MCPServerDTO>;
37
+ /**
38
+ * Update an MCP server
39
+ */
40
+ update(id: string, data: Partial<MCPServerDTO>): Promise<MCPServerDTO>;
41
+ /**
42
+ * Delete an MCP server
43
+ */
44
+ delete(id: string): Promise<void>;
45
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * MCP Servers API
3
+ */
4
+ export class MCPServersAPI {
5
+ constructor(http) {
6
+ this.http = http;
7
+ }
8
+ /**
9
+ * List public MCP servers
10
+ */
11
+ async list(params) {
12
+ return this.http.request('post', '/mcps/list', { data: params });
13
+ }
14
+ /**
15
+ * Get an MCP server by slug
16
+ */
17
+ async get(slug) {
18
+ return this.http.request('get', `/mcps/${slug}`);
19
+ }
20
+ /**
21
+ * List tools for an MCP server
22
+ */
23
+ async listTools(slug) {
24
+ return this.http.request('get', `/mcps/${slug}/tools`);
25
+ }
26
+ /**
27
+ * Call a tool on an MCP server
28
+ */
29
+ async callTool(slug, tool, input) {
30
+ return this.http.request('post', `/mcps/${slug}/tools/${tool}`, { data: input });
31
+ }
32
+ /**
33
+ * List user's own MCP servers
34
+ */
35
+ async listOwned(params) {
36
+ return this.http.request('post', '/mcp-servers/list', { data: params });
37
+ }
38
+ /**
39
+ * Get a user's MCP server by ID
40
+ */
41
+ async getOwned(id) {
42
+ return this.http.request('get', `/mcp-servers/${id}`);
43
+ }
44
+ /**
45
+ * Create an MCP server
46
+ */
47
+ async create(data) {
48
+ return this.http.request('post', '/mcp-servers', { data });
49
+ }
50
+ /**
51
+ * Update an MCP server
52
+ */
53
+ async update(id, data) {
54
+ return this.http.request('put', `/mcp-servers/${id}`, { data });
55
+ }
56
+ /**
57
+ * Delete an MCP server
58
+ */
59
+ async delete(id) {
60
+ return this.http.request('delete', `/mcp-servers/${id}`);
61
+ }
62
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,64 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { MCPServersAPI } from './mcp-servers';
3
+ const mockFetch = jest.fn();
4
+ global.fetch = mockFetch;
5
+ function mockJsonResponse(body) {
6
+ mockFetch.mockResolvedValueOnce({
7
+ ok: true,
8
+ status: 200,
9
+ text: () => Promise.resolve(JSON.stringify(body)),
10
+ });
11
+ }
12
+ describe('MCPServersAPI', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ const api = () => new MCPServersAPI(new HttpClient({ apiKey: 'test-key' }));
17
+ it('should POST /mcps/list for list()', async () => {
18
+ const page = { items: [{ slug: 'filesystem' }], next_cursor: null };
19
+ mockJsonResponse(page);
20
+ const result = await api().list();
21
+ expect(result).toEqual(page);
22
+ const [url, init] = mockFetch.mock.calls[0];
23
+ expect(url).toContain('/mcps/list');
24
+ expect(init.method).toBe('POST');
25
+ });
26
+ it('should GET /mcps/{slug}/tools for listTools()', async () => {
27
+ const tools = [{ name: 'read_file' }];
28
+ mockJsonResponse(tools);
29
+ const result = await api().listTools('filesystem');
30
+ expect(result).toEqual(tools);
31
+ const [url, init] = mockFetch.mock.calls[0];
32
+ expect(url).toContain('/mcps/filesystem/tools');
33
+ expect(init.method).toBe('GET');
34
+ });
35
+ it('should POST /mcps/{slug}/tools/{tool} for callTool()', async () => {
36
+ const input = { path: '/tmp/test.txt' };
37
+ const output = { content: 'hello' };
38
+ mockJsonResponse(output);
39
+ const result = await api().callTool('filesystem', 'read_file', input);
40
+ expect(result).toEqual(output);
41
+ const [url, init] = mockFetch.mock.calls[0];
42
+ expect(url).toContain('/mcps/filesystem/tools/read_file');
43
+ expect(init.method).toBe('POST');
44
+ expect(JSON.parse(init.body)).toEqual(input);
45
+ });
46
+ it('should POST /mcp-servers for create()', async () => {
47
+ const payload = { name: 'My MCP', slug: 'my-mcp' };
48
+ const server = { id: 'mcp-1', ...payload };
49
+ mockJsonResponse(server);
50
+ const result = await api().create(payload);
51
+ expect(result).toEqual(server);
52
+ const [url, init] = mockFetch.mock.calls[0];
53
+ expect(url).toContain('/mcp-servers');
54
+ expect(init.method).toBe('POST');
55
+ });
56
+ it('should PUT /mcp-servers/{id} for update()', async () => {
57
+ const server = { id: 'mcp-1', name: 'Updated MCP' };
58
+ mockJsonResponse(server);
59
+ await api().update('mcp-1', { name: 'Updated MCP' });
60
+ const [url, init] = mockFetch.mock.calls[0];
61
+ expect(url).toContain('/mcp-servers/mcp-1');
62
+ expect(init.method).toBe('PUT');
63
+ });
64
+ });
@@ -0,0 +1,29 @@
1
+ import { HttpClient } from '../http/client';
2
+ import { ProjectDTO, CursorListRequest, CursorListResponse } from '../types';
3
+ /**
4
+ * Projects API
5
+ */
6
+ export declare class ProjectsAPI {
7
+ private readonly http;
8
+ constructor(http: HttpClient);
9
+ /**
10
+ * List projects with cursor-based pagination
11
+ */
12
+ list(params?: Partial<CursorListRequest>): Promise<CursorListResponse<ProjectDTO>>;
13
+ /**
14
+ * Get a project by ID
15
+ */
16
+ get(id: string): Promise<ProjectDTO>;
17
+ /**
18
+ * Create a project
19
+ */
20
+ create(data: Partial<ProjectDTO>): Promise<ProjectDTO>;
21
+ /**
22
+ * Update a project
23
+ */
24
+ update(id: string, data: Partial<ProjectDTO>): Promise<ProjectDTO>;
25
+ /**
26
+ * Delete a project
27
+ */
28
+ delete(id: string): Promise<void>;
29
+ }