@oss-scout/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/dist/index.d.ts +1 -0
- package/dist/index.js +23 -0
- package/dist/mcp-server.bundle.cjs +38042 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.js +26 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.js +99 -0
- package/package.json +49 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function registerResources(server, scout) {
|
|
2
|
+
server.resource('config', 'scout://config', { description: 'Current oss-scout preferences' }, async () => ({
|
|
3
|
+
contents: [{
|
|
4
|
+
uri: 'scout://config',
|
|
5
|
+
mimeType: 'application/json',
|
|
6
|
+
text: JSON.stringify(scout.getPreferences(), null, 2),
|
|
7
|
+
}],
|
|
8
|
+
}));
|
|
9
|
+
server.resource('results', 'scout://results', { description: 'Saved search results from previous runs' }, async () => ({
|
|
10
|
+
contents: [{
|
|
11
|
+
uri: 'scout://results',
|
|
12
|
+
mimeType: 'application/json',
|
|
13
|
+
text: JSON.stringify(scout.getSavedResults(), null, 2),
|
|
14
|
+
}],
|
|
15
|
+
}));
|
|
16
|
+
server.resource('scores', 'scout://scores', { description: 'Repository score data based on contribution history' }, async () => {
|
|
17
|
+
const state = scout.getState();
|
|
18
|
+
return {
|
|
19
|
+
contents: [{
|
|
20
|
+
uri: 'scout://scores',
|
|
21
|
+
mimeType: 'application/json',
|
|
22
|
+
text: JSON.stringify(state.repoScores, null, 2),
|
|
23
|
+
}],
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
package/dist/tools.d.ts
ADDED
package/dist/tools.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SearchStrategySchema, ScoutPreferencesSchema } from '@oss-scout/core';
|
|
3
|
+
export function registerTools(server, scout) {
|
|
4
|
+
server.tool('search', 'Search for open source issues matching your preferences', {
|
|
5
|
+
maxResults: z.number().optional().describe('Maximum number of results to return (default 10)'),
|
|
6
|
+
strategies: z.string().optional().describe('Comma-separated search strategies: merged, orgs, starred, broad, maintained, all'),
|
|
7
|
+
}, async ({ maxResults, strategies }) => {
|
|
8
|
+
const parsedStrategies = strategies
|
|
9
|
+
? strategies.split(',').map((s) => SearchStrategySchema.parse(s.trim()))
|
|
10
|
+
: undefined;
|
|
11
|
+
const result = await scout.search({
|
|
12
|
+
maxResults: maxResults ?? 10,
|
|
13
|
+
strategies: parsedStrategies,
|
|
14
|
+
});
|
|
15
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
16
|
+
});
|
|
17
|
+
server.tool('vet', 'Vet a specific GitHub issue for contribution viability', {
|
|
18
|
+
issueUrl: z.string().describe('Full GitHub issue URL (e.g. https://github.com/owner/repo/issues/123)'),
|
|
19
|
+
}, async ({ issueUrl }) => {
|
|
20
|
+
const candidate = await scout.vetIssue(issueUrl);
|
|
21
|
+
return { content: [{ type: 'text', text: JSON.stringify(candidate, null, 2) }] };
|
|
22
|
+
});
|
|
23
|
+
server.tool('config', 'Show current oss-scout configuration preferences', async () => {
|
|
24
|
+
const preferences = scout.getPreferences();
|
|
25
|
+
return { content: [{ type: 'text', text: JSON.stringify(preferences, null, 2) }] };
|
|
26
|
+
});
|
|
27
|
+
const VALID_KEYS = Object.keys(ScoutPreferencesSchema.shape);
|
|
28
|
+
const ARRAY_KEYS = new Set([
|
|
29
|
+
'languages', 'labels', 'preferredOrgs', 'projectCategories',
|
|
30
|
+
'excludeRepos', 'aiPolicyBlocklist', 'scope', 'defaultStrategy',
|
|
31
|
+
]);
|
|
32
|
+
const NUMBER_KEYS = new Set(['minStars', 'maxIssueAgeDays', 'minRepoScoreThreshold']);
|
|
33
|
+
const BOOLEAN_KEYS = new Set(['includeDocIssues']);
|
|
34
|
+
server.tool('config-set', 'Update an oss-scout configuration preference', {
|
|
35
|
+
key: z.string().describe('Preference key to update (e.g. languages, minStars, excludeRepos)'),
|
|
36
|
+
value: z.string().describe('New value — comma-separated for arrays, plain string for scalars'),
|
|
37
|
+
}, async ({ key, value }) => {
|
|
38
|
+
if (!VALID_KEYS.includes(key)) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: 'text', text: `Unknown config key: "${key}". Valid keys: ${VALID_KEYS.join(', ')}` }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
let parsed;
|
|
45
|
+
if (ARRAY_KEYS.has(key)) {
|
|
46
|
+
// Accept comma-separated strings → arrays
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(value);
|
|
49
|
+
if (!Array.isArray(parsed)) {
|
|
50
|
+
parsed = value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
parsed = value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (NUMBER_KEYS.has(key)) {
|
|
58
|
+
const num = Number(value);
|
|
59
|
+
if (isNaN(num)) {
|
|
60
|
+
return {
|
|
61
|
+
content: [{ type: 'text', text: `Invalid number for "${key}": "${value}"` }],
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
parsed = num;
|
|
66
|
+
}
|
|
67
|
+
else if (BOOLEAN_KEYS.has(key)) {
|
|
68
|
+
const lower = value.toLowerCase();
|
|
69
|
+
if (lower === 'true' || lower === 'yes')
|
|
70
|
+
parsed = true;
|
|
71
|
+
else if (lower === 'false' || lower === 'no')
|
|
72
|
+
parsed = false;
|
|
73
|
+
else {
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: 'text', text: `Invalid boolean for "${key}": "${value}". Use true/false or yes/no.` }],
|
|
76
|
+
isError: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// String or enum fields — pass through as-is
|
|
82
|
+
parsed = value;
|
|
83
|
+
}
|
|
84
|
+
const currentPrefs = scout.getPreferences();
|
|
85
|
+
const candidate = { ...currentPrefs, [key]: parsed };
|
|
86
|
+
// Validate the full preferences object with Zod
|
|
87
|
+
const result = ScoutPreferencesSchema.safeParse(candidate);
|
|
88
|
+
if (!result.success) {
|
|
89
|
+
const issues = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: 'text', text: `Validation error: ${issues}` }],
|
|
92
|
+
isError: true,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
scout.updatePreferences({ [key]: parsed });
|
|
96
|
+
const updated = scout.getPreferences();
|
|
97
|
+
return { content: [{ type: 'text', text: JSON.stringify(updated, null, 2) }] };
|
|
98
|
+
});
|
|
99
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oss-scout/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for oss-scout — exposes issue discovery and vetting as MCP tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"oss-scout-mcp": "./dist/mcp-server.bundle.cjs"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"bundle": "esbuild src/index.ts --bundle --platform=node --target=node20 --format=cjs --outfile=dist/mcp-server.bundle.cjs",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"test:coverage": "vitest run --coverage",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"prepublishOnly": "pnpm run build && pnpm run bundle"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
29
|
+
"@oss-scout/core": "workspace:^",
|
|
30
|
+
"zod": "^4.3.6"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^25.5.0",
|
|
34
|
+
"esbuild": "^0.27.4",
|
|
35
|
+
"tsx": "^4.21.0",
|
|
36
|
+
"typescript": "^5.9.3",
|
|
37
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
38
|
+
"vitest": "^4.1.0"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20"
|
|
42
|
+
},
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/costajohnt/oss-scout.git",
|
|
47
|
+
"directory": "packages/mcp-server"
|
|
48
|
+
}
|
|
49
|
+
}
|