tascan-mcp 1.0.1 → 2.0.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 +171 -104
- package/index.js +199 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,153 +1,220 @@
|
|
|
1
|
-
# MCP
|
|
1
|
+
# TaScan MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI agent integration for [TaScan](https://tascan.io) — the closed-loop autonomous operations protocol. Manage projects, events, tasks, workers, QR codes, templates, completion reports, and AI-powered issue resolution through Claude, GitHub Copilot, or any MCP-compatible AI client.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Scan. Task. Done.**
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What is TaScan?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
TaScan is a zero-download task assignment and verification platform for physical-world work. Workers scan a QR code, complete tasks with photo verification, and managers get real-time completion reports — no app download, no login, no training required.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
When something breaks, AI analyzes the issue, generates fix instructions, and dispatches them to the right worker — closing the loop autonomously in under 10 seconds.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- **Adam Jones** (Anthropic) [@domdomegg](https://github.com/domdomegg)
|
|
15
|
-
- **Tadas Antanavicius** (PulseMCP) [@tadasant](https://github.com/tadasant)
|
|
16
|
-
- **Toby Padilla** (GitHub) [@toby](https://github.com/toby)
|
|
17
|
-
- **Radoslav (Rado) Dimitrov** (Stacklok) [@rdimitrov](https://github.com/rdimitrov)
|
|
13
|
+
Industries: live events, construction, hospitality, warehousing, property management, healthcare, aviation, FEMA disaster response, and more.
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
**Patent Pending** — USPTO #63/995,189 & #63/996,023
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
## Installation
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm install tascan-mcp
|
|
21
|
+
```
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
- **[Discussions](https://github.com/modelcontextprotocol/registry/discussions)** - Propose and discuss product/technical requirements
|
|
27
|
-
- **[Issues](https://github.com/modelcontextprotocol/registry/issues)** - Track well-scoped technical work
|
|
28
|
-
- **[Pull Requests](https://github.com/modelcontextprotocol/registry/pulls)** - Contribute work towards issues
|
|
23
|
+
Or run directly with npx:
|
|
29
24
|
|
|
30
|
-
|
|
25
|
+
```bash
|
|
26
|
+
npx tascan-mcp
|
|
27
|
+
```
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
## Configuration
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
- **Go 1.24.x**
|
|
36
|
-
- **ko** - Container image builder for Go ([installation instructions](https://ko.build/install/))
|
|
37
|
-
- **golangci-lint v2.4.0**
|
|
31
|
+
### Environment Variables
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
| Variable | Required | Description |
|
|
34
|
+
|----------|----------|-------------|
|
|
35
|
+
| `TASCAN_API_KEY` | Yes | Your TaScan API key (generate in Admin Portal > Team > API Keys) |
|
|
36
|
+
| `TASCAN_API_URL` | No | API base URL (default: `https://tascan-live-event.netlify.app/api/v1`) |
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
# Start full development environment
|
|
43
|
-
make dev-compose
|
|
44
|
-
```
|
|
38
|
+
### Claude Desktop
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
Add to your Claude Desktop config file (`claude_desktop_config.json`):
|
|
47
41
|
|
|
48
|
-
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"tascan": {
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "tascan-mcp"],
|
|
48
|
+
"env": {
|
|
49
|
+
"TASCAN_API_KEY": "your-api-key-here"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
### Claude Code
|
|
51
57
|
|
|
52
|
-
|
|
58
|
+
```bash
|
|
59
|
+
claude mcp add tascan -- npx -y tascan-mcp
|
|
60
|
+
```
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
<summary>Alternative: Running a pre-built Docker image</summary>
|
|
62
|
+
Then set your API key in the environment.
|
|
56
63
|
|
|
57
|
-
|
|
64
|
+
### Remote (claude.ai / Streamable HTTP)
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
# Run latest stable release
|
|
61
|
-
docker run -p 8080:8080 ghcr.io/modelcontextprotocol/registry:latest
|
|
66
|
+
TaScan MCP is also available as a remote server at:
|
|
62
67
|
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
```
|
|
69
|
+
https://tascan-live-event.netlify.app/mcp
|
|
70
|
+
```
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
Uses OAuth 2.0 with PKCE for authentication. No local installation required.
|
|
73
|
+
|
|
74
|
+
## Tools (27)
|
|
75
|
+
|
|
76
|
+
### Projects
|
|
77
|
+
| Tool | Description | Type |
|
|
78
|
+
|------|-------------|------|
|
|
79
|
+
| `tascan_list_projects` | List all projects in the organization | Read |
|
|
80
|
+
| `tascan_get_project` | Get details of a specific project | Read |
|
|
81
|
+
| `tascan_create_project` | Create a new project | Create |
|
|
82
|
+
| `tascan_update_project` | Update project name, location, status, dates | Update |
|
|
83
|
+
| `tascan_delete_project` | Delete a project and all its contents | Delete |
|
|
84
|
+
|
|
85
|
+
### Events (Task Lists)
|
|
86
|
+
| Tool | Description | Type |
|
|
87
|
+
|------|-------------|------|
|
|
88
|
+
| `tascan_list_events` | List all events within a project | Read |
|
|
89
|
+
| `tascan_get_event` | Get event details including tasks | Read |
|
|
90
|
+
| `tascan_create_event` | Create a new event in a project | Create |
|
|
91
|
+
| `tascan_update_event` | Update event name, description, modes | Update |
|
|
92
|
+
| `tascan_delete_event` | Delete an event and all its tasks | Delete |
|
|
93
|
+
|
|
94
|
+
### Tasks
|
|
95
|
+
| Tool | Description | Type |
|
|
96
|
+
|------|-------------|------|
|
|
97
|
+
| `tascan_list_tasks` | List all tasks in an event | Read |
|
|
98
|
+
| `tascan_get_task` | Get task details including completions | Read |
|
|
99
|
+
| `tascan_add_tasks` | Bulk-create tasks in an event | Create |
|
|
100
|
+
| `tascan_update_task` | Update task title, type, flags, order | Update |
|
|
101
|
+
| `tascan_delete_task` | Delete a task and its completions | Delete |
|
|
102
|
+
|
|
103
|
+
### Workers
|
|
104
|
+
| Tool | Description | Type |
|
|
105
|
+
|------|-------------|------|
|
|
106
|
+
| `tascan_list_workers` | List all workers in the organization | Read |
|
|
107
|
+
| `tascan_create_worker` | Create a new worker profile | Create |
|
|
108
|
+
| `tascan_update_worker` | Update worker name, phone, email | Update |
|
|
109
|
+
|
|
110
|
+
### Operations
|
|
111
|
+
| Tool | Description | Type |
|
|
112
|
+
|------|-------------|------|
|
|
113
|
+
| `tascan_generate_qr` | Generate a QR code for an event | Create |
|
|
114
|
+
| `tascan_apply_template` | Apply a pre-built template to an event | Create |
|
|
115
|
+
| `tascan_list_templates` | List available task templates | Read |
|
|
116
|
+
| `tascan_get_report` | Get completion report for an event | Read |
|
|
117
|
+
|
|
118
|
+
### Closed-Loop Autonomous Operations (Patent Pending)
|
|
119
|
+
| Tool | Description | Type |
|
|
120
|
+
|------|-------------|------|
|
|
121
|
+
| `tascan_list_issues` | List field-reported issues with filtering by status, category, severity | Read |
|
|
122
|
+
| `tascan_analyze_issue` | AI classifies issue severity, identifies root cause, and scores urgency | AI |
|
|
123
|
+
| `tascan_recommend_fix` | AI generates ranked remediation tasks with step-by-step instructions | AI |
|
|
124
|
+
| `tascan_dispatch_instruction` | Multi-channel delivery of fix instructions to workers (SMS, push, QR) | Create |
|
|
125
|
+
| `tascan_auto_resolve` | Full closed loop in ONE call — issue in, AI analyzes, fix dispatched, loop closes | AI |
|
|
126
|
+
|
|
127
|
+
## Usage Examples
|
|
128
|
+
|
|
129
|
+
### Example 1: Set up a construction site inspection
|
|
68
130
|
|
|
69
|
-
# Run development build from main branch
|
|
70
|
-
docker run -p 8080:8080 ghcr.io/modelcontextprotocol/registry:main-20250906-abc123d
|
|
71
131
|
```
|
|
132
|
+
User: Create a construction project for the Downtown Tower site and set up a daily safety inspection with tasks for PPE check, fall protection, scaffolding inspection, and fire extinguisher check. Make all tasks safety checkpoints that require photos.
|
|
72
133
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
134
|
+
Claude will:
|
|
135
|
+
1. Call tascan_create_project with name "Downtown Tower" and location "123 Main St"
|
|
136
|
+
2. Call tascan_create_event with name "Daily Safety Inspection"
|
|
137
|
+
3. Call tascan_add_tasks with 4 safety checkpoint tasks requiring photos
|
|
138
|
+
4. Call tascan_generate_qr to create a scannable QR code for the foreman
|
|
139
|
+
```
|
|
77
140
|
|
|
78
|
-
|
|
141
|
+
### Example 2: AI-powered autonomous issue resolution
|
|
79
142
|
|
|
80
|
-
|
|
143
|
+
```
|
|
144
|
+
User: Check if there are any open issues on the Marriott load-in and have TaScan fix them automatically.
|
|
81
145
|
|
|
82
|
-
|
|
146
|
+
Claude will:
|
|
147
|
+
1. Call tascan_list_issues to find open issues
|
|
148
|
+
2. Call tascan_auto_resolve for each issue — AI analyzes root cause, generates fix tasks, and dispatches instructions to the nearest qualified worker via SMS
|
|
149
|
+
3. Report back with resolution status and confidence scores
|
|
150
|
+
```
|
|
83
151
|
|
|
84
|
-
|
|
85
|
-
# Build the latest CLI
|
|
86
|
-
make publisher
|
|
152
|
+
### Example 3: Use templates to quickly deploy an event
|
|
87
153
|
|
|
88
|
-
|
|
89
|
-
|
|
154
|
+
```
|
|
155
|
+
User: We have a warehouse receiving shipment coming in tomorrow. Set up the standard receiving checklist.
|
|
156
|
+
|
|
157
|
+
Claude will:
|
|
158
|
+
1. Call tascan_list_templates with category "logistics" to find available templates
|
|
159
|
+
2. Call tascan_create_project for the warehouse
|
|
160
|
+
3. Call tascan_create_event for the receiving session
|
|
161
|
+
4. Call tascan_apply_template with the "warehouse-receiving" template slug
|
|
162
|
+
5. Call tascan_generate_qr for the receiving dock crew
|
|
90
163
|
```
|
|
91
164
|
|
|
92
|
-
|
|
165
|
+
### Example 4: Analyze and triage field issues
|
|
93
166
|
|
|
94
|
-
|
|
167
|
+
```
|
|
168
|
+
User: We have 5 open issues on the concert setup. Analyze them all and tell me which ones are most urgent.
|
|
95
169
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
170
|
+
Claude will:
|
|
171
|
+
1. Call tascan_list_issues to get all open issues
|
|
172
|
+
2. Call tascan_analyze_issue for each one — AI classifies severity, root cause probability, and urgency score
|
|
173
|
+
3. Rank by urgency and recommend which to auto-resolve vs which need human attention
|
|
99
174
|
```
|
|
100
175
|
|
|
101
|
-
|
|
176
|
+
## Task Types
|
|
102
177
|
|
|
103
|
-
|
|
104
|
-
For Claude and other AI tools: Always prefer make targets over custom commands where possible.
|
|
105
|
-
-->
|
|
178
|
+
Tasks support multiple response types:
|
|
106
179
|
|
|
107
|
-
|
|
180
|
+
| Type | Description |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `checkbox` | Simple done/not-done (default) |
|
|
183
|
+
| `photo` | Requires photo upload to complete |
|
|
184
|
+
| `text` | Free-text response |
|
|
185
|
+
| `number` | Numeric response |
|
|
186
|
+
| `date` | Date selection |
|
|
187
|
+
| `choice` | Multiple choice selection |
|
|
108
188
|
|
|
109
|
-
|
|
189
|
+
Tasks can also be flagged as:
|
|
190
|
+
- **Safety checkpoints** (`is_safety_checkpoint: true`) — highlighted in red, cannot be skipped
|
|
191
|
+
- **Photo required** (`requires_photo: true`) — worker must attach a photo to complete
|
|
110
192
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
│ ├── telemetry/ # Metrics and monitoring
|
|
124
|
-
│ └── validators/ # Input validation
|
|
125
|
-
├── pkg/ # Public packages
|
|
126
|
-
│ ├── api/ # API types and structures
|
|
127
|
-
│ │ └── v0/ # Version 0 API types
|
|
128
|
-
│ └── model/ # Data models for server.json
|
|
129
|
-
├── scripts/ # Development and testing scripts
|
|
130
|
-
├── tests/ # Integration tests
|
|
131
|
-
└── tools/ # CLI tools and utilities
|
|
132
|
-
└── validate-*.sh # Schema validation tools
|
|
133
|
-
```
|
|
193
|
+
## Getting an API Key
|
|
194
|
+
|
|
195
|
+
1. Log in to the [TaScan Admin Portal](https://tascan-live-event.netlify.app)
|
|
196
|
+
2. Navigate to **Team** in the sidebar
|
|
197
|
+
3. Scroll to **API Keys**
|
|
198
|
+
4. Click **Generate API Key**
|
|
199
|
+
5. Copy the key (it's only shown once)
|
|
200
|
+
6. Set it as `TASCAN_API_KEY` in your environment
|
|
201
|
+
|
|
202
|
+
API keys are scoped to your organization and support rate limiting (60 requests/minute).
|
|
203
|
+
|
|
204
|
+
## Privacy Policy
|
|
134
205
|
|
|
135
|
-
|
|
206
|
+
TaScan collects and processes task completion data, worker information (name, phone, email), GPS coordinates (with consent), and photos uploaded during task completion. Data is stored securely in Supabase with row-level security policies. API access is authenticated and rate-limited.
|
|
136
207
|
|
|
137
|
-
|
|
138
|
-
- **GitHub OAuth** - For publishing by logging into GitHub
|
|
139
|
-
- **GitHub OIDC** - For publishing from GitHub Actions
|
|
140
|
-
- **DNS verification** - For proving ownership of a domain and its subdomains
|
|
141
|
-
- **HTTP verification** - For proving ownership of a domain
|
|
208
|
+
For the full privacy policy, visit: https://tascan.io/faq.html
|
|
142
209
|
|
|
143
|
-
|
|
144
|
-
- `io.github.domdomegg/my-cool-mcp` you must login to GitHub as `domdomegg`, or be in a GitHub Action on domdomegg's repos
|
|
145
|
-
- `me.adamjones/my-cool-mcp` you must prove ownership of `adamjones.me` via DNS or HTTP challenge
|
|
210
|
+
For data deletion requests or privacy inquiries, contact: Michael@TaScan.io
|
|
146
211
|
|
|
147
|
-
##
|
|
212
|
+
## Support
|
|
148
213
|
|
|
149
|
-
|
|
214
|
+
- **Email:** Michael@TaScan.io
|
|
215
|
+
- **Website:** https://tascan.io
|
|
216
|
+
- **Issues:** https://github.com/snowbikemike/tascan-mcp/issues
|
|
150
217
|
|
|
151
|
-
##
|
|
218
|
+
## License
|
|
152
219
|
|
|
153
|
-
|
|
220
|
+
MIT License - Copyright (c) 2026 Michael Edward Love II / Love Productions LLC
|
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: '
|
|
49
|
+
version: '2.0.0'
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
|
|
@@ -662,6 +662,204 @@ server.registerTool(
|
|
|
662
662
|
);
|
|
663
663
|
|
|
664
664
|
|
|
665
|
+
// ─── Closed-Loop Autonomous Operations Protocol ───────────
|
|
666
|
+
|
|
667
|
+
// Tool 23: List Issues (discover issues for analysis)
|
|
668
|
+
server.registerTool(
|
|
669
|
+
'tascan_list_issues',
|
|
670
|
+
{
|
|
671
|
+
title: 'List Issues',
|
|
672
|
+
description: 'List all issues for a task list (event). Returns open, acknowledged, and resolved issues. Use to discover issues for AI analysis via tascan_analyze_issue.',
|
|
673
|
+
inputSchema: {
|
|
674
|
+
list_id: z.string().describe('Task list (event) ID')
|
|
675
|
+
},
|
|
676
|
+
annotations: {
|
|
677
|
+
readOnlyHint: true,
|
|
678
|
+
destructiveHint: false
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
async ({ list_id }) => {
|
|
682
|
+
const result = await apiCall('GET', `/lists/${list_id}/issues`);
|
|
683
|
+
const issues = result.data;
|
|
684
|
+
if (!issues.length) return { content: [{ type: 'text', text: 'No issues reported for this task list.' }] };
|
|
685
|
+
let text = `${issues.length} issue(s) found:\n\n`;
|
|
686
|
+
issues.forEach((iss, i) => {
|
|
687
|
+
text += `${i+1}. [${iss.status.toUpperCase()}] ${iss.title}\n`;
|
|
688
|
+
text += ` ID: ${iss.id} | Type: ${iss.type} | Category: ${iss.category} | Severity: ${iss.severity || 'unset'}\n`;
|
|
689
|
+
if (iss.tasks) text += ` Task: ${iss.tasks.title}\n`;
|
|
690
|
+
text += ` Reported: ${iss.created_at}\n\n`;
|
|
691
|
+
});
|
|
692
|
+
return { content: [{ type: 'text', text }] };
|
|
693
|
+
}
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
// Tool 24: Analyze Issue (Step 1 of Closed-Loop — read issue with full context + optional server AI)
|
|
697
|
+
server.registerTool(
|
|
698
|
+
'tascan_analyze_issue',
|
|
699
|
+
{
|
|
700
|
+
title: 'Analyze Issue',
|
|
701
|
+
description: 'Step 1 of the Closed-Loop Autonomous Operations Protocol. Returns full issue context including worker info, message thread, project history, and recent similar issues for AI reasoning. Supports optional server-side AI analysis via Anthropic API.',
|
|
702
|
+
inputSchema: {
|
|
703
|
+
issue_id: z.string().describe('Issue ID to analyze'),
|
|
704
|
+
server_side_ai: z.boolean().optional().describe('If true, server calls Anthropic API for analysis (default: false)')
|
|
705
|
+
},
|
|
706
|
+
annotations: {
|
|
707
|
+
readOnlyHint: false,
|
|
708
|
+
destructiveHint: false
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
async ({ issue_id, server_side_ai }) => {
|
|
712
|
+
if (server_side_ai) {
|
|
713
|
+
const result = await apiCall('POST', `/issues/${issue_id}/analyze`);
|
|
714
|
+
const d = result.data;
|
|
715
|
+
let text = `=== AI ANALYSIS (Server-Side) ===\n`;
|
|
716
|
+
text += `Issue: ${d.issue_title} (${d.issue_id})\nAnalyzed: ${d.analyzed_at}\n\n`;
|
|
717
|
+
text += JSON.stringify(d.analysis, null, 2);
|
|
718
|
+
return { content: [{ type: 'text', text }] };
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const result = await apiCall('GET', `/issues/${issue_id}`);
|
|
722
|
+
const d = result.data;
|
|
723
|
+
let text = `=== ISSUE CONTEXT FOR ANALYSIS ===\n`;
|
|
724
|
+
text += `Issue: ${d.title}\n`;
|
|
725
|
+
text += `Type: ${d.type} | Category: ${d.category} | Severity: ${d.severity || 'unset'} | Status: ${d.status}\n`;
|
|
726
|
+
text += `Description: ${d.description || 'none'}\n`;
|
|
727
|
+
if (d.tasks) text += `Task: ${d.tasks.title} (${d.tasks.response_type || 'checkbox'})\nTask Description: ${d.tasks.description || 'none'}\n`;
|
|
728
|
+
if (d.worker) text += `Worker: ${d.worker.name} (ID: ${d.worker.id})\n`;
|
|
729
|
+
if (d.project) text += `Project: ${d.project.name} | Location: ${d.project.location || 'unknown'}\n`;
|
|
730
|
+
if (d.injury_data) text += `Injury Data: ${JSON.stringify(d.injury_data)}\n`;
|
|
731
|
+
text += `Reported: ${d.created_at}\n`;
|
|
732
|
+
if (d.ai_analysis) text += `\n--- PREVIOUS AI ANALYSIS ---\n${JSON.stringify(d.ai_analysis, null, 2)}\n`;
|
|
733
|
+
if (d.messages && d.messages.length) {
|
|
734
|
+
text += `\n--- Message Thread (${d.messages.length}) ---\n`;
|
|
735
|
+
d.messages.forEach(m => { text += `[${m.sender_type}/${m.sender_name}] ${m.message}\n`; });
|
|
736
|
+
}
|
|
737
|
+
if (d.recent_issues && d.recent_issues.length) {
|
|
738
|
+
text += `\n--- Recent Issues on Same Project (${d.recent_issues.length}) ---\n`;
|
|
739
|
+
d.recent_issues.forEach(ri => { text += `- [${ri.severity}/${ri.category}] ${(ri.description || '').substring(0, 80)} (${ri.status})\n`; });
|
|
740
|
+
}
|
|
741
|
+
return { content: [{ type: 'text', text }] };
|
|
742
|
+
}
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
// Tool 25: Recommend Fix (Step 2 — post recommendation + optional structured tasks)
|
|
746
|
+
server.registerTool(
|
|
747
|
+
'tascan_recommend_fix',
|
|
748
|
+
{
|
|
749
|
+
title: 'Recommend Fix',
|
|
750
|
+
description: 'Step 2 of the Closed-Loop. Post AI recommendation to issue thread. Accepts optional structured_recommendation with task definitions for auto-dispatch. Persisted in AI audit trail.',
|
|
751
|
+
inputSchema: {
|
|
752
|
+
issue_id: z.string().describe('Issue ID to recommend a fix for'),
|
|
753
|
+
recommendation: z.string().describe('AI recommendation text (clear, actionable instructions)'),
|
|
754
|
+
structured_recommendation: z.any().optional().describe('Structured recommendation object with tasks for dispatch'),
|
|
755
|
+
ai_agent: z.string().optional().describe('AI agent name (default: TaScan AI)')
|
|
756
|
+
},
|
|
757
|
+
annotations: {
|
|
758
|
+
readOnlyHint: false,
|
|
759
|
+
destructiveHint: false
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
async ({ issue_id, recommendation, structured_recommendation, ai_agent }) => {
|
|
763
|
+
const body = { recommendation };
|
|
764
|
+
if (structured_recommendation) body.structured_recommendation = structured_recommendation;
|
|
765
|
+
if (ai_agent) body.ai_agent = ai_agent;
|
|
766
|
+
const result = await apiCall('POST', `/issues/${issue_id}/recommend`, body);
|
|
767
|
+
const d = result.data;
|
|
768
|
+
let text = `Recommendation posted to issue "${d.issue_title}":\n`;
|
|
769
|
+
text += `Project: ${d.project_name} | List: ${d.list_name}\n`;
|
|
770
|
+
text += `Message ID: ${d.message_id}\n\nRecommendation:\n${d.recommendation}`;
|
|
771
|
+
if (d.structured_recommendation?.tasks) {
|
|
772
|
+
text += `\n\nStructured Tasks (${d.structured_recommendation.tasks.length}):`;
|
|
773
|
+
d.structured_recommendation.tasks.forEach((t, i) => { text += `\n ${i+1}. ${t.title}`; });
|
|
774
|
+
}
|
|
775
|
+
return { content: [{ type: 'text', text }] };
|
|
776
|
+
}
|
|
777
|
+
);
|
|
778
|
+
|
|
779
|
+
// Tool 26: Dispatch Instruction (Step 3 — multi-channel delivery + task list creation)
|
|
780
|
+
server.registerTool(
|
|
781
|
+
'tascan_dispatch_instruction',
|
|
782
|
+
{
|
|
783
|
+
title: 'Dispatch Instruction',
|
|
784
|
+
description: 'Step 3 of the Closed-Loop. Multi-channel dispatch: issue thread, in-app message, progress feed, SMS, and optional remediation task list. Closes the loop from AI analysis to physical worker execution.',
|
|
785
|
+
inputSchema: {
|
|
786
|
+
issue_id: z.string().describe('Issue ID'),
|
|
787
|
+
instruction: z.string().describe('Actionable instruction for the worker'),
|
|
788
|
+
worker_id: z.string().optional().describe('Target worker ID (defaults to issue reporter)'),
|
|
789
|
+
remediation_tasks: z.array(z.any()).optional().describe('Tasks to create as remediation task list'),
|
|
790
|
+
recommendation_summary: z.string().optional().describe('Summary for task list description'),
|
|
791
|
+
send_sms: z.boolean().optional().describe('Send SMS (default: true if phone on file)'),
|
|
792
|
+
ai_agent: z.string().optional().describe('AI agent name (default: TaScan AI)')
|
|
793
|
+
},
|
|
794
|
+
annotations: {
|
|
795
|
+
readOnlyHint: false,
|
|
796
|
+
destructiveHint: false
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
async ({ issue_id, instruction, worker_id, remediation_tasks, recommendation_summary, send_sms, ai_agent }) => {
|
|
800
|
+
const body = { instruction };
|
|
801
|
+
if (worker_id) body.worker_id = worker_id;
|
|
802
|
+
if (remediation_tasks) body.remediation_tasks = remediation_tasks;
|
|
803
|
+
if (recommendation_summary) body.recommendation_summary = recommendation_summary;
|
|
804
|
+
if (send_sms !== undefined) body.send_sms = send_sms;
|
|
805
|
+
if (ai_agent) body.ai_agent = ai_agent;
|
|
806
|
+
const result = await apiCall('POST', `/issues/${issue_id}/dispatch`, body);
|
|
807
|
+
const d = result.data;
|
|
808
|
+
let text = `Dispatched via ${d.channels.length} channels: ${d.channels.join(', ')}\n`;
|
|
809
|
+
text += `Worker: ${d.worker_id} | Issue: ${d.issue_id} (${d.issue_status})\n`;
|
|
810
|
+
text += `SMS: ${d.sms_status}\n`;
|
|
811
|
+
if (d.remediation_task_list_id) {
|
|
812
|
+
text += `Task List: ${d.remediation_task_list_id}\nWorker URL: ${d.worker_url}\nTasks: ${d.tasks_created}\n`;
|
|
813
|
+
}
|
|
814
|
+
text += `\nInstruction:\n${d.instruction}`;
|
|
815
|
+
return { content: [{ type: 'text', text }] };
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
// Tool 27: Auto-Resolve (Full Closed-Loop in one call — Patent Claim 7)
|
|
820
|
+
server.registerTool(
|
|
821
|
+
'tascan_auto_resolve',
|
|
822
|
+
{
|
|
823
|
+
title: 'Auto-Resolve Issue',
|
|
824
|
+
description: 'FULL Closed-Loop Autonomous Operations Protocol in one call. Server-side AI analyzes issue, generates remediation tasks, creates task list, dispatches to worker via multi-channel delivery — all without human intervention. Patent Claim 7.',
|
|
825
|
+
inputSchema: {
|
|
826
|
+
issue_id: z.string().describe('Issue ID to auto-resolve')
|
|
827
|
+
},
|
|
828
|
+
annotations: {
|
|
829
|
+
readOnlyHint: false,
|
|
830
|
+
destructiveHint: false,
|
|
831
|
+
openWorldHint: true
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
async ({ issue_id }) => {
|
|
835
|
+
const result = await apiCall('POST', `/issues/${issue_id}/auto-resolve`);
|
|
836
|
+
const d = result.data;
|
|
837
|
+
let text = `=== CLOSED-LOOP AUTONOMOUS OPERATIONS PROTOCOL ===\n`;
|
|
838
|
+
text += `Issue: ${d.issue_id}\n\n`;
|
|
839
|
+
text += `--- ANALYSIS ---\n`;
|
|
840
|
+
text += `Summary: ${d.analysis?.summary || 'N/A'}\n`;
|
|
841
|
+
text += `Classification: ${d.analysis?.classification?.type || 'N/A'} (${d.analysis?.classification?.severity || 'N/A'})\n`;
|
|
842
|
+
text += `Urgency: ${d.analysis?.urgency_score || 'N/A'}/10\n`;
|
|
843
|
+
if (d.analysis?.root_cause_hypotheses?.length) {
|
|
844
|
+
d.analysis.root_cause_hypotheses.forEach((h, i) => {
|
|
845
|
+
text += ` ${i+1}. ${h.hypothesis} (${Math.round(h.confidence * 100)}%)\n`;
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
text += `\n--- RECOMMENDATION ---\n`;
|
|
849
|
+
text += `Fix: ${d.recommendation?.recommendation_summary || 'N/A'}\n`;
|
|
850
|
+
text += `Tasks: ${d.recommendation?.tasks?.length || 0}\n`;
|
|
851
|
+
text += `Duration: ${d.recommendation?.estimated_duration_minutes || 'N/A'} min\n`;
|
|
852
|
+
text += `\n--- DISPATCH ---\n`;
|
|
853
|
+
text += `Channels: ${d.dispatch?.channels?.join(', ') || 'none'}\n`;
|
|
854
|
+
text += `SMS: ${d.dispatch?.sms_status || 'N/A'}\n`;
|
|
855
|
+
if (d.dispatch?.worker_url) text += `Worker URL: ${d.dispatch.worker_url}\n`;
|
|
856
|
+
if (d.dispatch?.remediation_task_list_id) text += `Task List: ${d.dispatch.remediation_task_list_id}\n`;
|
|
857
|
+
text += `\nTimestamps: analyzed ${d.timestamps?.analyzed_at} | recommended ${d.timestamps?.recommended_at} | dispatched ${d.timestamps?.dispatched_at}`;
|
|
858
|
+
return { content: [{ type: 'text', text }] };
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
|
|
665
863
|
// ─── Start Server ──────────────────────────────────────────
|
|
666
864
|
async function main() {
|
|
667
865
|
const transport = new StdioServerTransport();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tascan-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"mcpName": "io.github.snowbikemike/tascan-mcp",
|
|
5
|
-
"description": "TaScan MCP Server —
|
|
5
|
+
"description": "TaScan MCP Server — Closed-loop autonomous operations protocol. 27 tools for projects, tasks, workers, QR codes, AI issue analysis, and autonomous remediation dispatch. Patent pending. Scan. Task. Done.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"bin": {
|