@missionsquad/mcp-msq 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 +232 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +75 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +13 -0
- package/dist/json.js.map +1 -0
- package/dist/msq-client.d.ts +42 -0
- package/dist/msq-client.js +218 -0
- package/dist/msq-client.js.map +1 -0
- package/dist/schemas.d.ts +644 -0
- package/dist/schemas.js +169 -0
- package/dist/schemas.js.map +1 -0
- package/dist/stdio-safe-console.d.ts +6 -0
- package/dist/stdio-safe-console.js +27 -0
- package/dist/stdio-safe-console.js.map +1 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.js +415 -0
- package/dist/tools.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# @missionsquad/mcp-msq
|
|
2
|
+
|
|
3
|
+
MCP server interface for the MissionSquad platform API (`https://missionsquad.ai`).
|
|
4
|
+
|
|
5
|
+
This server exposes MissionSquad account-scoped operations for models, agents, providers, vector stores, files, and core utilities via FastMCP tools.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- FastMCP stdio server (`mcp-msq`)
|
|
10
|
+
- MissionSquad API key support via hidden tool arg (`apiKey`) or env fallback (`MSQ_API_KEY`)
|
|
11
|
+
- MissionSquad base URL override via hidden tool arg (`baseUrl`) or env fallback (`MSQ_BASE_URL`)
|
|
12
|
+
- Strict TypeScript and Zod-validated tool inputs
|
|
13
|
+
- Multipart file upload support (`POST /v1/files`)
|
|
14
|
+
- Bounded binary file-content retrieval (`GET /v1/files/:id/content`) with truncation metadata
|
|
15
|
+
- Build/test CI and npm publish workflow
|
|
16
|
+
|
|
17
|
+
## Verified API Coverage
|
|
18
|
+
|
|
19
|
+
Implemented from `missionsquad-docs/api/index.md` and the following reference pages:
|
|
20
|
+
|
|
21
|
+
- `chat-completions.md`
|
|
22
|
+
- `embeddings.md`
|
|
23
|
+
- `providers.md`
|
|
24
|
+
- `models.md`
|
|
25
|
+
- `agents.md`
|
|
26
|
+
- `core-utilities.md`
|
|
27
|
+
- `collections.md`
|
|
28
|
+
- `vector-stores.md`
|
|
29
|
+
- `files.md`
|
|
30
|
+
- `convenience.md`
|
|
31
|
+
- `endpoint-index.md`
|
|
32
|
+
|
|
33
|
+
Current implementation intentionally excludes Webhooks endpoints because the reference only lists routes without request/response contracts.
|
|
34
|
+
|
|
35
|
+
## Requirements
|
|
36
|
+
|
|
37
|
+
- Node.js `>=20`
|
|
38
|
+
- Yarn
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
yarn install
|
|
44
|
+
yarn build
|
|
45
|
+
yarn start
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Run as CLI after install/publish:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mcp-msq
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
Copy `.env.example` to `.env`.
|
|
57
|
+
|
|
58
|
+
| Variable | Required | Default | Description |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `MSQ_API_KEY` | No | unset | MissionSquad API key fallback when hidden `apiKey` is not passed |
|
|
61
|
+
| `MSQ_BASE_URL` | No | `https://agents.missionsquad.ai/v1` | Base URL for v1 endpoints |
|
|
62
|
+
| `MSQ_HTTP_TIMEOUT_MS` | No | `30000` | Request timeout in milliseconds |
|
|
63
|
+
| `MSQ_DEFAULT_FILE_CONTENT_MAX_BYTES` | No | `1048576` | Default max bytes returned by `msq_get_file_content` |
|
|
64
|
+
|
|
65
|
+
## Hidden Arguments
|
|
66
|
+
|
|
67
|
+
The following are intentionally not in tool schemas and should be passed as hidden extra args:
|
|
68
|
+
|
|
69
|
+
- `apiKey`: MissionSquad API key for request authentication
|
|
70
|
+
- `baseUrl`: Optional base URL override
|
|
71
|
+
|
|
72
|
+
Resolution order per request:
|
|
73
|
+
|
|
74
|
+
1. Hidden extra arg
|
|
75
|
+
2. Environment fallback
|
|
76
|
+
|
|
77
|
+
If no API key is available, the tool returns a user-facing error.
|
|
78
|
+
|
|
79
|
+
## Tool Surface
|
|
80
|
+
|
|
81
|
+
### Core OpenAI-Compatible
|
|
82
|
+
|
|
83
|
+
- `msq_list_models`
|
|
84
|
+
- `msq_get_model_map`
|
|
85
|
+
- `msq_chat_completions`
|
|
86
|
+
- `msq_embeddings`
|
|
87
|
+
|
|
88
|
+
### Providers
|
|
89
|
+
|
|
90
|
+
- `msq_list_providers`
|
|
91
|
+
- `msq_add_provider`
|
|
92
|
+
- `msq_delete_provider`
|
|
93
|
+
|
|
94
|
+
### Models
|
|
95
|
+
|
|
96
|
+
- `msq_discover_provider_models`
|
|
97
|
+
- `msq_add_model`
|
|
98
|
+
- `msq_delete_model`
|
|
99
|
+
|
|
100
|
+
### Agents
|
|
101
|
+
|
|
102
|
+
- `msq_list_agents`
|
|
103
|
+
- `msq_add_agent`
|
|
104
|
+
- `msq_delete_agent`
|
|
105
|
+
|
|
106
|
+
### Core Utilities
|
|
107
|
+
|
|
108
|
+
- `msq_generate_prompt`
|
|
109
|
+
- `msq_run_agent_workflow`
|
|
110
|
+
- `msq_get_core_config`
|
|
111
|
+
- `msq_scrape_url`
|
|
112
|
+
- `msq_list_tools`
|
|
113
|
+
- `msq_list_servers`
|
|
114
|
+
|
|
115
|
+
### Core Collections
|
|
116
|
+
|
|
117
|
+
- `msq_list_core_collections`
|
|
118
|
+
- `msq_search_core_collection`
|
|
119
|
+
- `msq_get_core_collection_diagnostics`
|
|
120
|
+
- `msq_recover_core_collection`
|
|
121
|
+
|
|
122
|
+
### Vector Stores
|
|
123
|
+
|
|
124
|
+
- `msq_list_vector_stores`
|
|
125
|
+
- `msq_create_vector_store`
|
|
126
|
+
- `msq_get_vector_store`
|
|
127
|
+
- `msq_delete_vector_store`
|
|
128
|
+
- `msq_list_vector_store_files`
|
|
129
|
+
- `msq_add_vector_store_file`
|
|
130
|
+
- `msq_get_vector_store_file`
|
|
131
|
+
- `msq_cancel_vector_store_session`
|
|
132
|
+
|
|
133
|
+
### Files
|
|
134
|
+
|
|
135
|
+
- `msq_list_files`
|
|
136
|
+
- `msq_upload_file`
|
|
137
|
+
- `msq_get_file`
|
|
138
|
+
- `msq_delete_file`
|
|
139
|
+
- `msq_get_file_content`
|
|
140
|
+
|
|
141
|
+
### Convenience
|
|
142
|
+
|
|
143
|
+
- `msq_list_user_collections`
|
|
144
|
+
- `msq_get_vector_store_file_details`
|
|
145
|
+
|
|
146
|
+
## File Upload and Download Notes
|
|
147
|
+
|
|
148
|
+
`msq_upload_file` accepts:
|
|
149
|
+
|
|
150
|
+
- `filePath` (required)
|
|
151
|
+
- `purpose` (required)
|
|
152
|
+
- `relativePath` (optional)
|
|
153
|
+
- `collectionName` (optional)
|
|
154
|
+
- `filename` (optional override)
|
|
155
|
+
|
|
156
|
+
`msq_get_file_content` returns:
|
|
157
|
+
|
|
158
|
+
- `contentType`
|
|
159
|
+
- `contentLength`
|
|
160
|
+
- `bytesRead`
|
|
161
|
+
- `truncated`
|
|
162
|
+
- `base64`
|
|
163
|
+
|
|
164
|
+
If response content exceeds `maxBytes` (or `MSQ_DEFAULT_FILE_CONTENT_MAX_BYTES`), payload is truncated safely and reported via `truncated: true`.
|
|
165
|
+
|
|
166
|
+
## Response Format
|
|
167
|
+
|
|
168
|
+
All tool handlers return deterministic JSON text strings. Parse text content on the client side if structured access is needed.
|
|
169
|
+
|
|
170
|
+
## Usage Examples
|
|
171
|
+
|
|
172
|
+
### JSON-RPC tools/call with hidden API key
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"method": "tools/call",
|
|
177
|
+
"params": {
|
|
178
|
+
"name": "msq_list_models",
|
|
179
|
+
"arguments": {
|
|
180
|
+
"apiKey": "msq-..."
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### JSON-RPC tools/call with body args
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"method": "tools/call",
|
|
191
|
+
"params": {
|
|
192
|
+
"name": "msq_chat_completions",
|
|
193
|
+
"arguments": {
|
|
194
|
+
"model": "my-gpt4",
|
|
195
|
+
"messages": [
|
|
196
|
+
{ "role": "user", "content": "Hello" }
|
|
197
|
+
],
|
|
198
|
+
"apiKey": "msq-..."
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### FastMCP-style client call
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
await client.callTool('msq_embeddings', {
|
|
208
|
+
model: 'nomic-embed-text-v1.5',
|
|
209
|
+
input: ['First sentence', 'Second sentence'],
|
|
210
|
+
apiKey: 'msq-...',
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Development
|
|
215
|
+
|
|
216
|
+
Scripts:
|
|
217
|
+
|
|
218
|
+
- `yarn build`
|
|
219
|
+
- `yarn start`
|
|
220
|
+
- `yarn dev`
|
|
221
|
+
- `yarn inspect`
|
|
222
|
+
- `yarn test`
|
|
223
|
+
- `yarn test:coverage`
|
|
224
|
+
|
|
225
|
+
## CI/CD
|
|
226
|
+
|
|
227
|
+
- `.github/workflows/build.yaml`: build + test on PR open/sync
|
|
228
|
+
- `.github/workflows/publish.yaml`: build + test + publish on `main` push (markdown-only changes ignored)
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const DEFAULT_HTTP_TIMEOUT_MS = 30000;
|
|
2
|
+
export declare const DEFAULT_FILE_CONTENT_MAX_BYTES = 1048576;
|
|
3
|
+
export interface AppConfig {
|
|
4
|
+
defaultApiKey: string | undefined;
|
|
5
|
+
defaultBaseUrl: string;
|
|
6
|
+
httpTimeoutMs: number;
|
|
7
|
+
defaultFileContentMaxBytes: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ResolvedRequestConfig {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
httpTimeoutMs: number;
|
|
13
|
+
defaultFileContentMaxBytes: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const appConfig: AppConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve authentication and base URL for a request.
|
|
18
|
+
* Hidden extra args take precedence over environment defaults.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveRequestConfig(extraArgs: Record<string, unknown> | undefined, defaults?: AppConfig): ResolvedRequestConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { UserError } from '@missionsquad/fastmcp';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { MsqConfigError } from './errors.js';
|
|
5
|
+
dotenv.config();
|
|
6
|
+
const DEFAULT_BASE_URL = 'https://agents.missionsquad.ai/v1';
|
|
7
|
+
const EXPECTED_BASE_PATH_SUFFIX = '/v1';
|
|
8
|
+
export const DEFAULT_HTTP_TIMEOUT_MS = 30_000;
|
|
9
|
+
export const DEFAULT_FILE_CONTENT_MAX_BYTES = 1_048_576;
|
|
10
|
+
const EnvSchema = z.object({
|
|
11
|
+
MSQ_API_KEY: z.string().optional(),
|
|
12
|
+
MSQ_BASE_URL: z.string().optional(),
|
|
13
|
+
MSQ_HTTP_TIMEOUT_MS: z.coerce.number().int().positive().optional(),
|
|
14
|
+
MSQ_DEFAULT_FILE_CONTENT_MAX_BYTES: z.coerce.number().int().positive().optional(),
|
|
15
|
+
});
|
|
16
|
+
const env = EnvSchema.parse(process.env);
|
|
17
|
+
function normalizeBaseUrl(rawUrl) {
|
|
18
|
+
const trimmed = rawUrl.trim();
|
|
19
|
+
if (trimmed.length === 0) {
|
|
20
|
+
throw new MsqConfigError('MissionSquad base URL must be a non-empty string.');
|
|
21
|
+
}
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = new URL(trimmed);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new MsqConfigError(`MissionSquad base URL is invalid: ${trimmed}`);
|
|
28
|
+
}
|
|
29
|
+
parsed.search = '';
|
|
30
|
+
parsed.hash = '';
|
|
31
|
+
const normalizedPath = parsed.pathname.replace(/\/+$/, '') || '/';
|
|
32
|
+
parsed.pathname = normalizedPath;
|
|
33
|
+
if (!normalizedPath.endsWith(EXPECTED_BASE_PATH_SUFFIX)) {
|
|
34
|
+
console.warn(`[mcp-msq] Base URL path "${normalizedPath}" does not end with "${EXPECTED_BASE_PATH_SUFFIX}".` +
|
|
35
|
+
' MissionSquad API requests may fail if this is not a v1 API base URL.');
|
|
36
|
+
}
|
|
37
|
+
return parsed.toString().replace(/\/$/, '');
|
|
38
|
+
}
|
|
39
|
+
function readHiddenString(extraArgs, key) {
|
|
40
|
+
const value = extraArgs?.[key];
|
|
41
|
+
if (value === undefined) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
if (typeof value !== 'string') {
|
|
45
|
+
throw new UserError(`Hidden argument "${key}" must be a string when provided.`);
|
|
46
|
+
}
|
|
47
|
+
const trimmed = value.trim();
|
|
48
|
+
if (trimmed.length === 0) {
|
|
49
|
+
throw new UserError(`Hidden argument "${key}" must be a non-empty string when provided.`);
|
|
50
|
+
}
|
|
51
|
+
return trimmed;
|
|
52
|
+
}
|
|
53
|
+
export const appConfig = {
|
|
54
|
+
defaultApiKey: env.MSQ_API_KEY?.trim() || undefined,
|
|
55
|
+
defaultBaseUrl: normalizeBaseUrl(env.MSQ_BASE_URL ?? DEFAULT_BASE_URL),
|
|
56
|
+
httpTimeoutMs: env.MSQ_HTTP_TIMEOUT_MS ?? DEFAULT_HTTP_TIMEOUT_MS,
|
|
57
|
+
defaultFileContentMaxBytes: env.MSQ_DEFAULT_FILE_CONTENT_MAX_BYTES ?? DEFAULT_FILE_CONTENT_MAX_BYTES,
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Resolve authentication and base URL for a request.
|
|
61
|
+
* Hidden extra args take precedence over environment defaults.
|
|
62
|
+
*/
|
|
63
|
+
export function resolveRequestConfig(extraArgs, defaults = appConfig) {
|
|
64
|
+
const apiKey = readHiddenString(extraArgs, 'apiKey') ?? defaults.defaultApiKey;
|
|
65
|
+
if (apiKey === undefined || apiKey.trim().length === 0) {
|
|
66
|
+
throw new UserError('MissionSquad API key is required. Provide hidden argument "apiKey" or set MSQ_API_KEY.');
|
|
67
|
+
}
|
|
68
|
+
const hiddenBaseUrl = readHiddenString(extraArgs, 'baseUrl');
|
|
69
|
+
const baseUrl = hiddenBaseUrl ? normalizeBaseUrl(hiddenBaseUrl) : defaults.defaultBaseUrl;
|
|
70
|
+
return {
|
|
71
|
+
apiKey: apiKey.trim(),
|
|
72
|
+
baseUrl,
|
|
73
|
+
httpTimeoutMs: defaults.httpTimeoutMs,
|
|
74
|
+
defaultFileContentMaxBytes: defaults.defaultFileContentMaxBytes,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { UserError } from '@missionsquad/fastmcp';
|
|
2
|
+
export declare class MsqConfigError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class MsqTransportError extends Error {
|
|
6
|
+
constructor(message: string, cause?: unknown);
|
|
7
|
+
}
|
|
8
|
+
export declare class MsqApiError extends Error {
|
|
9
|
+
readonly status: number;
|
|
10
|
+
readonly statusText: string;
|
|
11
|
+
readonly url: string;
|
|
12
|
+
readonly responseBody: unknown;
|
|
13
|
+
constructor(message: string, status: number, statusText: string, url: string, responseBody: unknown);
|
|
14
|
+
}
|
|
15
|
+
export declare function toUserError(error: unknown, prefix: string): UserError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { UserError } from '@missionsquad/fastmcp';
|
|
2
|
+
export class MsqConfigError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = 'MsqConfigError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class MsqTransportError extends Error {
|
|
9
|
+
constructor(message, cause) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'MsqTransportError';
|
|
12
|
+
if (cause !== undefined) {
|
|
13
|
+
this.cause = cause;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class MsqApiError extends Error {
|
|
18
|
+
status;
|
|
19
|
+
statusText;
|
|
20
|
+
url;
|
|
21
|
+
responseBody;
|
|
22
|
+
constructor(message, status, statusText, url, responseBody) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.status = status;
|
|
25
|
+
this.statusText = statusText;
|
|
26
|
+
this.url = url;
|
|
27
|
+
this.responseBody = responseBody;
|
|
28
|
+
this.name = 'MsqApiError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function messageFromResponseBody(responseBody) {
|
|
32
|
+
if (typeof responseBody === 'string') {
|
|
33
|
+
const trimmed = responseBody.trim();
|
|
34
|
+
if (trimmed.length > 0)
|
|
35
|
+
return trimmed;
|
|
36
|
+
return 'No response body.';
|
|
37
|
+
}
|
|
38
|
+
if (responseBody === null || typeof responseBody !== 'object') {
|
|
39
|
+
return 'No response body.';
|
|
40
|
+
}
|
|
41
|
+
const record = responseBody;
|
|
42
|
+
const error = record.error;
|
|
43
|
+
if (typeof error === 'string' && error.trim().length > 0) {
|
|
44
|
+
return error;
|
|
45
|
+
}
|
|
46
|
+
if (error !== null && typeof error === 'object') {
|
|
47
|
+
const errorRecord = error;
|
|
48
|
+
const nestedMessage = errorRecord.message;
|
|
49
|
+
if (typeof nestedMessage === 'string' && nestedMessage.trim().length > 0) {
|
|
50
|
+
return nestedMessage;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const message = record.message;
|
|
54
|
+
if (typeof message === 'string' && message.trim().length > 0) {
|
|
55
|
+
return message;
|
|
56
|
+
}
|
|
57
|
+
return 'No response body.';
|
|
58
|
+
}
|
|
59
|
+
export function toUserError(error, prefix) {
|
|
60
|
+
if (error instanceof UserError) {
|
|
61
|
+
return error;
|
|
62
|
+
}
|
|
63
|
+
if (error instanceof MsqApiError) {
|
|
64
|
+
const bodyMessage = messageFromResponseBody(error.responseBody);
|
|
65
|
+
return new UserError(`${prefix}: MissionSquad API returned ${error.status} ${error.statusText}. ${bodyMessage}`);
|
|
66
|
+
}
|
|
67
|
+
if (error instanceof MsqConfigError || error instanceof MsqTransportError) {
|
|
68
|
+
return new UserError(`${prefix}: ${error.message}`);
|
|
69
|
+
}
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
return new UserError(`${prefix}: ${error.message}`);
|
|
72
|
+
}
|
|
73
|
+
return new UserError(`${prefix}: ${String(error)}`);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { FastMCP } from '@missionsquad/fastmcp';
|
|
3
|
+
import { routeConsoleStdoutToStderr } from './stdio-safe-console.js';
|
|
4
|
+
import { registerMissionSquadTools } from './tools.js';
|
|
5
|
+
routeConsoleStdoutToStderr();
|
|
6
|
+
const server = new FastMCP({
|
|
7
|
+
name: 'mcp-msq',
|
|
8
|
+
version: '0.1.0',
|
|
9
|
+
});
|
|
10
|
+
registerMissionSquadTools(server);
|
|
11
|
+
async function main() {
|
|
12
|
+
await server.start({ transportType: 'stdio' });
|
|
13
|
+
}
|
|
14
|
+
async function shutdown(exitCode) {
|
|
15
|
+
try {
|
|
16
|
+
await server.stop();
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
process.exit(exitCode);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
process.on('SIGINT', () => {
|
|
23
|
+
void shutdown(0);
|
|
24
|
+
});
|
|
25
|
+
process.on('SIGTERM', () => {
|
|
26
|
+
void shutdown(0);
|
|
27
|
+
});
|
|
28
|
+
process.on('uncaughtException', () => {
|
|
29
|
+
void shutdown(1);
|
|
30
|
+
});
|
|
31
|
+
process.on('unhandledRejection', () => {
|
|
32
|
+
void shutdown(1);
|
|
33
|
+
});
|
|
34
|
+
void main().catch(() => {
|
|
35
|
+
void shutdown(1);
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAEtD,0BAA0B,EAAE,CAAA;AAE5B,MAAM,MAAM,GAAG,IAAI,OAAO,CAAY;IACpC,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,OAAO;CACjB,CAAC,CAAA;AAEF,yBAAyB,CAAC,MAAM,CAAC,CAAA;AAEjC,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAA;AAChD,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;IACrB,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACxB,CAAC;AACH,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACnC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;IACpC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IACrB,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC,CAAC,CAAA"}
|
package/dist/json.d.ts
ADDED
package/dist/json.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tools commonly return a string payload. This keeps output deterministic.
|
|
3
|
+
*/
|
|
4
|
+
export function stringifyResult(value) {
|
|
5
|
+
const result = JSON.stringify(value, (_key, currentValue) => {
|
|
6
|
+
if (typeof currentValue === 'bigint') {
|
|
7
|
+
return currentValue.toString();
|
|
8
|
+
}
|
|
9
|
+
return currentValue;
|
|
10
|
+
}, 2);
|
|
11
|
+
return result ?? 'null';
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=json.js.map
|
package/dist/json.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAC3B,KAAK,EACL,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE;QACrB,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO,YAAY,CAAC,QAAQ,EAAE,CAAA;QAChC,CAAC;QACD,OAAO,YAAY,CAAA;IACrB,CAAC,EACD,CAAC,CACF,CAAA;IAED,OAAO,MAAM,IAAI,MAAM,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ResolvedRequestConfig } from './config.js';
|
|
2
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
3
|
+
interface JsonRequestOptions {
|
|
4
|
+
method: HttpMethod;
|
|
5
|
+
path: string;
|
|
6
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
headers?: Record<string, string | undefined>;
|
|
9
|
+
}
|
|
10
|
+
interface FileUploadOptions {
|
|
11
|
+
filePath: string;
|
|
12
|
+
purpose: string;
|
|
13
|
+
relativePath?: string;
|
|
14
|
+
collectionName?: string;
|
|
15
|
+
filename?: string;
|
|
16
|
+
}
|
|
17
|
+
interface FileContentRequestOptions {
|
|
18
|
+
fileId: string;
|
|
19
|
+
maxBytes?: number;
|
|
20
|
+
}
|
|
21
|
+
interface FileContentResult {
|
|
22
|
+
contentType: string | null;
|
|
23
|
+
contentLength: number | null;
|
|
24
|
+
bytesRead: number;
|
|
25
|
+
truncated: boolean;
|
|
26
|
+
base64: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class MissionSquadClient {
|
|
29
|
+
private readonly requestConfig;
|
|
30
|
+
constructor(requestConfig: ResolvedRequestConfig);
|
|
31
|
+
requestJson(options: JsonRequestOptions): Promise<unknown>;
|
|
32
|
+
uploadFile(options: FileUploadOptions): Promise<unknown>;
|
|
33
|
+
getFileContent(options: FileContentRequestOptions): Promise<FileContentResult>;
|
|
34
|
+
private buildUrl;
|
|
35
|
+
private compactHeaders;
|
|
36
|
+
private fetchWithTimeout;
|
|
37
|
+
private parseStructuredResponse;
|
|
38
|
+
private parseResponseBody;
|
|
39
|
+
private parseErrorPayload;
|
|
40
|
+
}
|
|
41
|
+
export declare function createMissionSquadClient(extraArgs: Record<string, unknown> | undefined): MissionSquadClient;
|
|
42
|
+
export {};
|