tascan-mcp 2.3.0 → 2.4.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/index.js +89 -1
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -46,7 +46,7 @@ async function apiCall(method, path, body) {
|
|
|
46
46
|
// ─── Server Setup ──────────────────────────────────────────
|
|
47
47
|
const server = new McpServer({
|
|
48
48
|
name: 'tascan',
|
|
49
|
-
version: '2.
|
|
49
|
+
version: '2.4.0'
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
|
|
@@ -860,6 +860,94 @@ server.registerTool(
|
|
|
860
860
|
);
|
|
861
861
|
|
|
862
862
|
|
|
863
|
+
// ─── NFC Tag Registry ─────────────────────────────────────
|
|
864
|
+
|
|
865
|
+
// Tool 28: Register NFC Tag
|
|
866
|
+
server.registerTool(
|
|
867
|
+
'tascan_register_tag',
|
|
868
|
+
{
|
|
869
|
+
title: 'Register NFC Tag',
|
|
870
|
+
description: 'Register a physical NFC tag to a project, task list, or specific task. When someone taps the tag, TaScan routes them to the linked resource. Tags use NTAG215 chips and are programmed with NFC Tools Pro.',
|
|
871
|
+
inputSchema: {
|
|
872
|
+
tag_hardware_id: z.string().describe('NFC tag hardware serial number (e.g., "04:CB:6C:51:CE:2A:81")'),
|
|
873
|
+
tag_name: z.string().describe('Friendly name (e.g., "Ballroom A Door", "Breaker Panel 3")'),
|
|
874
|
+
target_type: z.enum(['project', 'task_list', 'task']).describe('What this tag points to'),
|
|
875
|
+
project_id: z.string().optional().describe('Project ID'),
|
|
876
|
+
task_list_id: z.string().optional().describe('Task list ID (required for task_list/task targets)'),
|
|
877
|
+
task_id: z.string().optional().describe('Task ID (required for task targets)'),
|
|
878
|
+
location_description: z.string().optional().describe('Physical location of the tag')
|
|
879
|
+
},
|
|
880
|
+
annotations: { readOnlyHint: false, destructiveHint: false }
|
|
881
|
+
},
|
|
882
|
+
async ({ tag_hardware_id, tag_name, target_type, project_id, task_list_id, task_id, location_description }) => {
|
|
883
|
+
const result = await apiCall('POST', '/tags', {
|
|
884
|
+
tag_hardware_id, tag_name, target_type, project_id, task_list_id, task_id, location_description
|
|
885
|
+
});
|
|
886
|
+
const d = result.data;
|
|
887
|
+
const nfcUrl = 'https://app.tascan.io/scan?tag={TAG-ID}&time={DATETIME}';
|
|
888
|
+
return {
|
|
889
|
+
content: [{
|
|
890
|
+
type: 'text',
|
|
891
|
+
text: `Tag registered: "${d.tag_name}" (${d.tag_hardware_id})\nTarget: ${d.target_type}\nID: ${d.id}\n\nProgram the NFC tag with this URL:\n${nfcUrl}\n\n${JSON.stringify(d, null, 2)}`
|
|
892
|
+
}]
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
// Tool 29: List Tags
|
|
898
|
+
server.registerTool(
|
|
899
|
+
'tascan_list_tags',
|
|
900
|
+
{
|
|
901
|
+
title: 'List NFC Tags',
|
|
902
|
+
description: 'List all registered NFC tags in the organization with their linked projects/task lists and scan counts',
|
|
903
|
+
inputSchema: {},
|
|
904
|
+
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
905
|
+
},
|
|
906
|
+
async () => {
|
|
907
|
+
const result = await apiCall('GET', '/tags');
|
|
908
|
+
const tags = result.data;
|
|
909
|
+
if (!tags.length) return { content: [{ type: 'text', text: 'No NFC tags registered.' }] };
|
|
910
|
+
let text = `${tags.length} tag(s) registered:\n\n`;
|
|
911
|
+
tags.forEach((t, i) => {
|
|
912
|
+
text += `${i+1}. "${t.tag_name}" — ${t.tag_hardware_id}\n`;
|
|
913
|
+
text += ` Target: ${t.target_type} | Scans: ${t.scan_count} | Active: ${t.is_active}\n`;
|
|
914
|
+
if (t.projects) text += ` Project: ${t.projects.name}\n`;
|
|
915
|
+
if (t.task_lists) text += ` Task List: ${t.task_lists.name}\n`;
|
|
916
|
+
if (t.location_description) text += ` Location: ${t.location_description}\n`;
|
|
917
|
+
text += '\n';
|
|
918
|
+
});
|
|
919
|
+
return { content: [{ type: 'text', text }] };
|
|
920
|
+
}
|
|
921
|
+
);
|
|
922
|
+
|
|
923
|
+
// Tool 30: Get Scan History
|
|
924
|
+
server.registerTool(
|
|
925
|
+
'tascan_get_scan_history',
|
|
926
|
+
{
|
|
927
|
+
title: 'Get Scan History',
|
|
928
|
+
description: 'Get scan event history for a registered NFC tag — timestamps, GPS coordinates, and accuracy for each scan',
|
|
929
|
+
inputSchema: {
|
|
930
|
+
tag_id: z.string().describe('Tag registry ID (from tascan_list_tags)'),
|
|
931
|
+
limit: z.number().optional().describe('Max results (default 50)')
|
|
932
|
+
},
|
|
933
|
+
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
934
|
+
},
|
|
935
|
+
async ({ tag_id, limit }) => {
|
|
936
|
+
const path = `/tags/${tag_id}/scans` + (limit ? `?limit=${limit}` : '');
|
|
937
|
+
const result = await apiCall('GET', path);
|
|
938
|
+
const scans = result.data;
|
|
939
|
+
if (!scans.length) return { content: [{ type: 'text', text: 'No scans recorded for this tag.' }] };
|
|
940
|
+
let text = `${scans.length} scan(s):\n\n`;
|
|
941
|
+
scans.forEach((s, i) => {
|
|
942
|
+
text += `${i+1}. ${s.scanned_at}`;
|
|
943
|
+
if (s.gps_lat && s.gps_lng) text += ` — GPS: ${s.gps_lat.toFixed(6)}, ${s.gps_lng.toFixed(6)} (±${Math.round(s.gps_accuracy || 0)}m)`;
|
|
944
|
+
text += '\n';
|
|
945
|
+
});
|
|
946
|
+
return { content: [{ type: 'text', text }] };
|
|
947
|
+
}
|
|
948
|
+
);
|
|
949
|
+
|
|
950
|
+
|
|
863
951
|
// ─── Start Server ──────────────────────────────────────────
|
|
864
952
|
async function main() {
|
|
865
953
|
const transport = new StdioServerTransport();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tascan-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"mcpName": "io.github.snowbikemike/tascan-mcp",
|
|
5
|
-
"description": "TaScan MCP Server — Closed-loop autonomous operations protocol.
|
|
5
|
+
"description": "TaScan MCP Server — Closed-loop autonomous operations protocol. 30 tools for projects, tasks, workers, QR codes, NFC tag registry, scan verification, AI issue analysis, and autonomous remediation dispatch. 12 patents filed (335+ claims). Task. Scan. Done.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"bin": {
|