Skip to content

Commit 5651b9f

Browse files
adileiadilei
andauthored
Rename mcp folders (#411)
* Remove empty .gitignore file from MCP folder * Rename MCP to MCPSamples and search-species-resources to search-species-resources-typescript * Add 'How It Works' section to README with implementation examples --------- Co-authored-by: adilei <[email protected]>
1 parent 9dc841b commit 5651b9f

37 files changed

+221
-112
lines changed

MCP/search-species-resources/README.md

Lines changed: 0 additions & 112 deletions
This file was deleted.
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Biological Species MCP Server
2+
3+
An MCP server demonstrating resource discovery through tools. Copilot Studio always accesses resources through tools, not directly - a design motivated by enterprise environments with large-scale resource catalogs.
4+
5+
## Architecture
6+
7+
**How Copilot Studio accesses MCP resources:**
8+
- Copilot Studio uses tools to discover resources (never enumerates all resources directly)
9+
- Tools return filtered resource references (e.g., search returns 5 matches)
10+
- Agent evaluates references and selectively reads chosen resources
11+
- Design enables scalability for enterprise systems with large resource catalogs
12+
13+
**Note:** The MCP protocol supports direct resource enumeration, but Copilot Studio's architecture always uses tool-based discovery.
14+
15+
This server implements a simple search pattern with fuzzy matching.
16+
17+
## How It Works
18+
19+
**1. Define Your Resources**
20+
21+
Resources are dynamically generated from a species database:
22+
23+
```typescript
24+
// Species data with details
25+
export const SPECIES_DATA: Species[] = [
26+
{
27+
id: "monarch-butterfly",
28+
commonName: "Monarch Butterfly",
29+
scientificName: "Danaus plexippus",
30+
description: "Famous for its distinctive orange and black wing pattern...",
31+
habitat: "North America, with migration routes...",
32+
diet: "Larvae feed on milkweed; adults feed on nectar",
33+
conservationStatus: "Vulnerable",
34+
interestingFacts: [...],
35+
tags: ["insect", "butterfly", "migration"],
36+
image: encodeImage("butterfly.png")
37+
},
38+
// ... more species
39+
];
40+
41+
// Resources generated from species data
42+
export const RESOURCES: SpeciesResource[] = [
43+
{
44+
uri: "species://blue-whale/overview",
45+
name: "Blue Whale Overview",
46+
description: "Comprehensive information about blue whales",
47+
mimeType: "text/plain",
48+
speciesId: "blue-whale",
49+
resourceType: "text"
50+
},
51+
{
52+
uri: "species://blue-whale/photo",
53+
name: "Blue Whale Photo",
54+
description: "High-resolution photo of a blue whale",
55+
mimeType: "image/png",
56+
speciesId: "blue-whale",
57+
resourceType: "image"
58+
},
59+
// ... more resources
60+
];
61+
```
62+
63+
This generates 8 resources from 5 species (5 text overviews + 3 images).
64+
65+
**2. Implement Search Tool**
66+
67+
The `searchSpeciesData` tool uses Fuse.js for fuzzy matching and returns `resource_link` references:
68+
69+
```typescript
70+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
71+
if (request.params.name === "searchSpeciesData") {
72+
const searchResults = fuse.search(searchTerms);
73+
const topResults = searchResults.slice(0, 5);
74+
75+
// Return resource references, not full content
76+
const content = [
77+
{
78+
type: "text",
79+
text: `Found ${topResults.length} resources matching "${searchTerms}"`
80+
}
81+
];
82+
83+
topResults.forEach(result => {
84+
content.push({
85+
type: "resource_link",
86+
uri: result.item.uri,
87+
name: result.item.name,
88+
description: result.item.description,
89+
mimeType: result.item.mimeType,
90+
annotations: {
91+
audience: ["assistant"],
92+
priority: 0.8
93+
}
94+
});
95+
});
96+
97+
return { content };
98+
}
99+
});
100+
```
101+
102+
**3. Handle Resource Reads**
103+
104+
When the agent sends `resources/read` requests, your server provides the full content:
105+
106+
```typescript
107+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
108+
const uri = request.params.uri;
109+
const resource = RESOURCES.find(r => r.uri === uri);
110+
const species = SPECIES_DATA.find(s => s.id === resource.speciesId);
111+
112+
if (resource.resourceType === 'text') {
113+
return {
114+
contents: [{
115+
uri,
116+
mimeType: "text/plain",
117+
text: formatSpeciesText(species)
118+
}]
119+
};
120+
}
121+
122+
if (resource.resourceType === 'image') {
123+
return {
124+
contents: [{
125+
uri,
126+
mimeType: "image/png",
127+
blob: species.image // Base64-encoded PNG
128+
}]
129+
};
130+
}
131+
});
132+
```
133+
134+
## Sample Structure
135+
136+
```
137+
src/
138+
├── index.ts # Server entry point
139+
├── types.ts # TypeScript types
140+
├── data/
141+
│ ├── species.ts # Species data (5 species)
142+
│ └── resources.ts # Resource definitions (8 resources)
143+
├── assets/ # PNG images
144+
└── utils/ # Utilities (datetime, formatting, image encoding)
145+
```
146+
147+
## Quick Start
148+
149+
### Prerequisites
150+
151+
- Node.js 18+
152+
- [Dev Tunnels CLI](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started)
153+
- Copilot Studio access
154+
155+
### 1. Install and Build
156+
157+
```bash
158+
npm install
159+
npm run build
160+
```
161+
162+
### 2. Start Server
163+
164+
```bash
165+
npm start
166+
# or
167+
npm run dev
168+
```
169+
170+
Server runs on `http://localhost:3000/mcp`
171+
172+
### 3. Create Dev Tunnel
173+
174+
**VS Code:**
175+
1. Ports panel → Forward Port → 3000
176+
2. Right-click → Port Visibility → Public
177+
3. Copy HTTPS URL
178+
179+
**CLI:**
180+
```bash
181+
devtunnel host -p 3000 --allow-anonymous
182+
```
183+
184+
**Important:** URL format is `https://abc123-3000.devtunnels.ms/mcp` (port in hostname with hyphen, not colon)
185+
186+
### 4. Configure Copilot Studio
187+
188+
1. Navigate to Tools → Add tool → Model Context Protocol
189+
2. Configure:
190+
- **Server URL:** `https://your-tunnel-3000.devtunnels.ms/mcp`
191+
- **Authentication:** None
192+
3. Click Create
193+
194+
## Example Queries
195+
196+
```
197+
What species do you have?
198+
→ Calls listSpecies()
199+
200+
Tell me about butterflies
201+
→ Calls searchSpeciesData("butterflies") → Returns Monarch Butterfly resources
202+
203+
Show me a blue whale photo
204+
→ Calls searchSpeciesData("blue whale photo") → Returns image resource
205+
```
206+
207+
## Development
208+
209+
### Adding Species
210+
211+
1. Add to `src/data/species.ts`
212+
2. Add PNG to `src/assets/`
213+
3. Add resources to `src/data/resources.ts`
214+
4. Rebuild: `npm run build`
215+
216+
## Resources
217+
218+
- [Model Context Protocol](https://modelcontextprotocol.io/)
219+
- [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk)
220+
- [MCP in Copilot Studio][(https://copilotstudio.microsoft.com](https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-mcp))
221+
- [Dev Tunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview)

0 commit comments

Comments
 (0)