tender-mcp 1.2.3 → 1.2.4
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/server.js +16 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.2.4] - 2026-04-27
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- `token_count` field on all tool responses — lets orchestrator budget ledgers track token cost per call
|
|
5
|
+
- `/ready` endpoint — returns 200 when `ANTHROPIC_API_KEY` and `SAM_GOV_API_KEY` are present, 503 otherwise
|
|
6
|
+
- Phase 4 enhanced error objects: `category`, `retryable`, `retry_after_ms`, `fallback_tool`, `trace_id` on all error paths across both tools
|
|
7
|
+
|
|
1
8
|
## [1.2.3] - 2026-04-26
|
|
2
9
|
|
|
3
10
|
### Improved
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tender-mcp",
|
|
3
3
|
"mcpName": "io.github.OjasKord/tender-mcp",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.4",
|
|
5
5
|
"description": "Government tender search and AI opportunity scoring for AI agents. UK Contracts Finder, EU TED, US SAM.gov.",
|
|
6
6
|
"main": "src/server.js",
|
|
7
7
|
"scripts": {
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.OjasKord/tender-mcp",
|
|
4
4
|
"title": "Tender MCP",
|
|
5
5
|
"description": "Government tender search for AI agents. UK, EU and US procurement opportunities.",
|
|
6
|
-
"version": "1.2.
|
|
6
|
+
"version": "1.2.4",
|
|
7
7
|
"websiteUrl": "https://kordagencies.com",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/OjasKord/tender-mcp",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "tender-mcp",
|
|
16
|
-
"version": "1.2.
|
|
16
|
+
"version": "1.2.4",
|
|
17
17
|
"transport": { "type": "stdio" },
|
|
18
18
|
"environmentVariables": [
|
|
19
19
|
{ "name": "ANTHROPIC_API_KEY", "description": "Anthropic API key for AI-powered tender scoring", "isRequired": true, "isSecret": true }
|
package/src/server.js
CHANGED
|
@@ -3,7 +3,7 @@ const https = require('https');
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
|
|
6
|
-
const VERSION = '1.2.
|
|
6
|
+
const VERSION = '1.2.4';
|
|
7
7
|
const PERSIST_FILE = '/tmp/tender_stats.json';
|
|
8
8
|
const RESEND_API_KEY = process.env.RESEND_API_KEY || '';
|
|
9
9
|
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '';
|
|
@@ -296,7 +296,7 @@ async function executeTool(name, args, tier) {
|
|
|
296
296
|
// ── TOOL 1: search_tenders ──────────────────────────────────────────────────
|
|
297
297
|
if (name === 'search_tenders') {
|
|
298
298
|
const { keyword, company_profile, sources = ['uk', 'eu', 'us'], limit, days_old, min_score } = args;
|
|
299
|
-
if (!keyword) return { error: 'keyword is required', agent_action: 'PROVIDE_REQUIRED_FIELD', _disclaimer: LEGAL_DISCLAIMER };
|
|
299
|
+
if (!keyword) return { error: 'keyword is required', agent_action: 'PROVIDE_REQUIRED_FIELD', category: 'invalid_input', retryable: false, retry_after_ms: null, fallback_tool: 'search_tenders', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER };
|
|
300
300
|
|
|
301
301
|
const fetchLimit = Math.min(limit || 10, 25);
|
|
302
302
|
const daysOld = days_old || 30;
|
|
@@ -384,12 +384,12 @@ async function executeTool(name, args, tier) {
|
|
|
384
384
|
// ── TOOL 2: get_tender_intelligence ────────────────────────────────────────
|
|
385
385
|
if (name === 'get_tender_intelligence') {
|
|
386
386
|
const { mode, keywords, keyword, sources = ['uk', 'eu', 'us'], limit } = args;
|
|
387
|
-
if (!mode) return { error: 'mode is required: DAILY_DIGEST or AWARD_HISTORY', agent_action: 'PROVIDE_REQUIRED_FIELD', _disclaimer: LEGAL_DISCLAIMER };
|
|
387
|
+
if (!mode) return { error: 'mode is required: DAILY_DIGEST or AWARD_HISTORY', agent_action: 'PROVIDE_REQUIRED_FIELD', category: 'invalid_input', retryable: false, retry_after_ms: null, fallback_tool: 'get_tender_intelligence', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER };
|
|
388
388
|
|
|
389
389
|
// ── DAILY_DIGEST ──
|
|
390
390
|
if (mode === 'DAILY_DIGEST') {
|
|
391
391
|
if (!keywords || !Array.isArray(keywords) || keywords.length === 0) {
|
|
392
|
-
return { error: 'keywords array is required for DAILY_DIGEST mode', agent_action: 'PROVIDE_REQUIRED_FIELD', _disclaimer: LEGAL_DISCLAIMER };
|
|
392
|
+
return { error: 'keywords array is required for DAILY_DIGEST mode', agent_action: 'PROVIDE_REQUIRED_FIELD', category: 'invalid_input', retryable: false, retry_after_ms: null, fallback_tool: 'get_tender_intelligence', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER };
|
|
393
393
|
}
|
|
394
394
|
|
|
395
395
|
// Free tier preview: run one keyword, return count only — no full results
|
|
@@ -456,7 +456,7 @@ async function executeTool(name, args, tier) {
|
|
|
456
456
|
|
|
457
457
|
// ── AWARD_HISTORY ──
|
|
458
458
|
if (mode === 'AWARD_HISTORY') {
|
|
459
|
-
if (!keyword) return { error: 'keyword is required for AWARD_HISTORY mode', agent_action: 'PROVIDE_REQUIRED_FIELD', _disclaimer: LEGAL_DISCLAIMER };
|
|
459
|
+
if (!keyword) return { error: 'keyword is required for AWARD_HISTORY mode', agent_action: 'PROVIDE_REQUIRED_FIELD', category: 'invalid_input', retryable: false, retry_after_ms: null, fallback_tool: 'get_tender_intelligence', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER };
|
|
460
460
|
const maxResults = Math.min(limit || 10, 25);
|
|
461
461
|
|
|
462
462
|
// Free tier preview: run search, return winner count + one sample name only
|
|
@@ -524,10 +524,10 @@ async function executeTool(name, args, tier) {
|
|
|
524
524
|
};
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
-
return { error: 'Invalid mode. Use DAILY_DIGEST or AWARD_HISTORY.', agent_action: 'PROVIDE_REQUIRED_FIELD', _disclaimer: LEGAL_DISCLAIMER };
|
|
527
|
+
return { error: 'Invalid mode. Use DAILY_DIGEST or AWARD_HISTORY.', agent_action: 'PROVIDE_REQUIRED_FIELD', category: 'invalid_input', retryable: false, retry_after_ms: null, fallback_tool: 'get_tender_intelligence', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER };
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
-
return { error: 'Unknown tool: ' + name, agent_action: 'RETRY_IN_2_MIN' };
|
|
530
|
+
return { error: 'Unknown tool: ' + name, agent_action: 'RETRY_IN_2_MIN', category: 'unknown_tool', retryable: false, retry_after_ms: null, fallback_tool: null, trace_id: Math.random().toString(36).slice(2, 10) };
|
|
531
531
|
}
|
|
532
532
|
|
|
533
533
|
// ─── ACCESS CONTROL ───────────────────────────────────────────────────────────
|
|
@@ -614,9 +614,17 @@ const server = http.createServer(async (req, res) => {
|
|
|
614
614
|
return;
|
|
615
615
|
}
|
|
616
616
|
|
|
617
|
+
if (req.url === '/ready' && (req.method === 'GET' || req.method === 'HEAD')) {
|
|
618
|
+
const checks = { anthropic: !!ANTHROPIC_API_KEY, sam_gov: !!SAM_GOV_API_KEY };
|
|
619
|
+
const ready = checks.anthropic && checks.sam_gov;
|
|
620
|
+
res.writeHead(ready ? 200 : 503, { ...cors, 'Content-Type': 'application/json' });
|
|
621
|
+
res.end(JSON.stringify({ status: ready ? 'ready' : 'not_ready', version: VERSION, checks }));
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
617
625
|
if (req.url === '/.well-known/mcp/server-card.json') {
|
|
618
626
|
res.writeHead(200, { ...cors, 'Content-Type': 'application/json' });
|
|
619
|
-
res.end(JSON.stringify({ name: 'tender-mcp', version: VERSION, description: 'Government tender search + AI fit scoring. UK, EU, US. Free tier: 10 searches/month.', tools: tools.map(t => ({ name: t.name, description: t.description.slice(0, 100) })), transport: '
|
|
627
|
+
res.end(JSON.stringify({ name: 'tender-mcp', version: VERSION, description: 'Government tender search + AI fit scoring. UK, EU, US. Free tier: 10 searches/month.', tools: tools.map(t => ({ name: t.name, description: t.description.slice(0, 100) })), transport: 'streamable-http', homepage: 'https://kordagencies.com', author: 'ojas1', token_footprint_min: 300, token_footprint_max: 800, token_footprint_avg: 550, idempotent_tools: ['search_tenders', 'get_tender_intelligence'], circuit_breaker: false, health_endpoint: '/health', ready_endpoint: '/ready' }));
|
|
620
628
|
return;
|
|
621
629
|
}
|
|
622
630
|
|