Skip to content

Commit 295468e

Browse files
committed
docs(stubs): enhance documentation and examples for MCP stubs
(cherry picked from commit d4d3eb4)
1 parent 9e5e3bb commit 295468e

File tree

4 files changed

+497
-44
lines changed

4 files changed

+497
-44
lines changed

src/stubs/prompt.stub

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ use OPGG\LaravelMcpServer\Services\PromptService\Prompt;
3434
* - description: string (optional) - Explains what this argument is for
3535
* - required: bool (optional, default: false) - Whether this argument must be provided
3636
*
37-
* USAGE EXAMPLE:
38-
* -------------
37+
* USAGE EXAMPLES:
38+
* ===============
39+
*
40+
* Basic Usage:
3941
* When a client requests this prompt:
4042
* {
4143
* "method": "prompts/get",
@@ -48,17 +50,69 @@ use OPGG\LaravelMcpServer\Services\PromptService\Prompt;
4850
* }
4951
* }
5052
*
51-
* The response will contain the processed prompt with placeholders replaced.
53+
* Advanced Usage with cURL:
54+
* curl -X POST http://localhost:8000/mcp \
55+
* -H "Content-Type: application/json" \
56+
* -d '{
57+
* "jsonrpc": "2.0",
58+
* "id": 1,
59+
* "method": "prompts/get",
60+
* "params": {
61+
* "name": "{{ name }}",
62+
* "arguments": {
63+
* "example_arg": "AI Assistant",
64+
* "optional_arg": "Advanced Mode"
65+
* }
66+
* }
67+
* }'
68+
*
69+
* Testing with Artisan:
70+
* php artisan mcp:test-tool --list
71+
*
72+
* Using MCP Inspector:
73+
* npx @modelcontextprotocol/inspector
74+
* # Then connect to your Laravel server endpoint
75+
*
76+
* ADVANCED PROMPT PATTERNS:
77+
* ========================
78+
*
79+
* Multi-Message Prompts:
80+
* You can return arrays of messages for complex interactions:
81+
* return [
82+
* ['role' => 'system', 'content' => 'You are a helpful assistant...'],
83+
* ['role' => 'user', 'content' => $this->text],
84+
* ];
85+
*
86+
* Conditional Content:
87+
* Use PHP logic to customize prompts based on arguments:
88+
* $content = "Base prompt text";
89+
* if ($arguments['advanced_mode']) {
90+
* $content .= " Include technical details and advanced options.";
91+
* }
92+
*
93+
* Resource References:
94+
* Include references to your resources in prompts:
95+
* "Analyze the data from file:///logs/{date}.log and provide insights."
96+
*
97+
* Tool Integration:
98+
* Guide LLMs on which tools to use:
99+
* "Use the search-products tool to find items matching {criteria}."
52100
*
53101
* @see https://modelcontextprotocol.io/docs/concepts/prompts
54102
*/
55103
class {{ className }} extends Prompt
56104
{
57105
/**
58106
* Unique identifier for this prompt.
59-
* Best practice: Use descriptive kebab-case names.
107+
* Used by clients to request this specific prompt.
108+
*
109+
* NAMING BEST PRACTICES:
110+
* - Use descriptive, action-oriented names
111+
* - Include context or domain when relevant
112+
* - Examples: 'analyze-sales-data', 'debug-api-error', 'generate-user-report'
113+
* - Use kebab-case naming convention
60114
*/
61-
public string $name = 'example-prompt';
115+
public string $name = '{{ name }}';
62116

63117
/**
64118
* Optional description shown in prompt listings.

src/stubs/resource.stub

Lines changed: 150 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,65 @@ use Illuminate\Support\Facades\File;
5656
class {{ className }} extends Resource
5757
{
5858
/**
59-
* Unique URI for this resource.
60-
* Choose a URI scheme that makes sense for your resource type.
59+
* Unique URI identifier for this resource.
60+
*
61+
* URI SCHEME EXAMPLES:
62+
* - file:///path/to/file.txt (file system)
63+
* - database://table/id (database records)
64+
* - api://service/endpoint (external APIs)
65+
* - config://section (configuration data)
66+
* - logs://date/type (log files)
67+
* - cache://key (cached data)
68+
*
69+
* BEST PRACTICES:
70+
* - Use descriptive paths that indicate content
71+
* - Include version numbers for APIs: api://v1/users
72+
* - Use timestamps for time-sensitive data: logs://2024-01-15
73+
* - Be consistent across similar resources
6174
*/
62-
public string $uri = 'file:///path/to/resource.txt';
75+
public string $uri = 'file:///example/{{ className|lower }}.txt';
6376

6477
/**
6578
* Display name for this resource.
66-
* Make it descriptive so users know what they're accessing.
79+
* Shown in resource listings and client UIs.
80+
*
81+
* NAMING GUIDELINES:
82+
* - Use clear, descriptive names
83+
* - Include data type or source
84+
* - Consider user perspective
85+
* - Examples: "Application Logs", "User Database", "Sales Report"
6786
*/
68-
public string $name = 'Example Resource Name';
87+
public string $name = '{{ className }}';
6988

7089
/**
71-
* Optional description providing context.
72-
* Explain what this resource contains and when it's useful.
90+
* Detailed description of what this resource contains.
91+
*
92+
* DESCRIPTION BEST PRACTICES:
93+
* - Explain what data is available
94+
* - Mention update frequency or freshness
95+
* - Note any access requirements or limitations
96+
* - Include examples of use cases
97+
* - Specify data format and structure
98+
*
99+
* EXAMPLES:
100+
* "Real-time application logs from the last 24 hours. Updated continuously. Contains error messages, request traces, and performance metrics."
101+
* "Complete user database with profiles, preferences, and activity history. Updated in real-time. Use for user analysis and support."
73102
*/
74-
public ?string $description = 'This resource provides [describe what it contains and its purpose]';
103+
public ?string $description = 'A {{ className|lower }} resource that provides access to [describe your specific data source]. Replace this with details about what data is available, how often it updates, and when it should be used.';
75104

76105
/**
77106
* MIME type of the resource content.
78-
* Common types: text/plain, application/json, text/csv, image/png
107+
* Helps clients understand how to process the data.
108+
*
109+
* COMMON MIME TYPES:
110+
* - text/plain: Plain text files, logs
111+
* - application/json: JSON data, API responses
112+
* - text/csv: CSV files, exported data
113+
* - application/xml: XML documents, configs
114+
* - text/html: HTML content, reports
115+
* - image/png, image/jpeg: Images, charts
116+
* - application/pdf: PDF documents, reports
117+
* - text/markdown: Markdown documentation
79118
*/
80119
public ?string $mimeType = 'text/plain';
81120

@@ -127,11 +166,110 @@ class {{ className }} extends Resource
127166
// 'text' => json_encode($data, JSON_PRETTY_PRINT),
128167
// ];
129168

130-
// Default implementation - replace with your logic
169+
// TODO: Replace this example with your actual resource reading logic
170+
171+
// === IMPLEMENTATION EXAMPLES ===
172+
// Choose the pattern that best fits your resource:
173+
174+
// --- File System Resource ---
175+
// $filePath = storage_path('app/data/example.txt');
176+
// if (!File::exists($filePath)) {
177+
// throw new \Exception("File not found: {$this->uri}");
178+
// }
179+
// $content = File::get($filePath);
180+
// return [
181+
// 'uri' => $this->uri,
182+
// 'mimeType' => $this->mimeType,
183+
// 'text' => $content,
184+
// ];
185+
186+
// --- Database Resource ---
187+
// $data = collect([
188+
// 'users_count' => User::count(),
189+
// 'active_sessions' => Session::where('last_activity', '>', now()->subHour())->count(),
190+
// 'recent_orders' => Order::where('created_at', '>', now()->subDay())->count(),
191+
// 'generated_at' => now()->toISOString(),
192+
// ]);
193+
// return [
194+
// 'uri' => $this->uri,
195+
// 'mimeType' => 'application/json',
196+
// 'text' => $data->toJson(JSON_PRETTY_PRINT),
197+
// ];
198+
199+
// --- External API Resource ---
200+
// $response = Http::timeout(10)
201+
// ->withHeaders(['Authorization' => 'Bearer ' . config('services.api.token')])
202+
// ->get('https://api.example.com/data');
203+
// if (!$response->successful()) {
204+
// throw new \Exception("API request failed: {$response->status()}");
205+
// }
206+
// return [
207+
// 'uri' => $this->uri,
208+
// 'mimeType' => 'application/json',
209+
// 'text' => $response->body(),
210+
// ];
211+
212+
// --- Configuration Resource ---
213+
// $config = [
214+
// 'app_name' => config('app.name'),
215+
// 'environment' => config('app.env'),
216+
// 'debug_mode' => config('app.debug'),
217+
// 'timezone' => config('app.timezone'),
218+
// 'features' => [
219+
// 'mcp_enabled' => config('mcp-server.enabled'),
220+
// 'tools_count' => count(config('mcp-server.tools')),
221+
// ],
222+
// ];
223+
// return [
224+
// 'uri' => $this->uri,
225+
// 'mimeType' => 'application/json',
226+
// 'text' => json_encode($config, JSON_PRETTY_PRINT),
227+
// ];
228+
229+
// --- Log File Resource ---
230+
// $logPath = storage_path('logs/laravel.log');
231+
// if (!File::exists($logPath)) {
232+
// return [
233+
// 'uri' => $this->uri,
234+
// 'mimeType' => 'text/plain',
235+
// 'text' => 'No log file found.',
236+
// ];
237+
// }
238+
// $content = File::get($logPath);
239+
// return [
240+
// 'uri' => $this->uri,
241+
// 'mimeType' => 'text/plain',
242+
// 'text' => $content,
243+
// ];
244+
245+
// Default example implementation
246+
$exampleData = [
247+
'resource_name' => '{{ className }}',
248+
'generated_at' => now()->toISOString(),
249+
'sample_data' => [
250+
'message' => 'This is example content from {{ className }}',
251+
'instructions' => 'Replace this with your actual resource data',
252+
'suggestions' => [
253+
'What data should this resource provide?',
254+
'How often does it change?',
255+
'What format is most useful for consumers?',
256+
'Are there any access restrictions?',
257+
'Should it include metadata or just raw data?',
258+
],
259+
],
260+
'implementation_tips' => [
261+
'Use try-catch for error handling',
262+
'Consider caching for expensive operations',
263+
'Validate access permissions if needed',
264+
'Include helpful metadata in responses',
265+
'Test with different scenarios and edge cases',
266+
],
267+
];
268+
131269
return [
132270
'uri' => $this->uri,
133-
'mimeType' => $this->mimeType,
134-
'text' => "Replace this with actual content from your data source.\n\nThis could be:\n- File contents\n- Database query results\n- API responses\n- Generated reports\n- Or any other data",
271+
'mimeType' => 'application/json',
272+
'text' => json_encode($exampleData, JSON_PRETTY_PRINT),
135273
];
136274

137275
} catch (\Exception $e) {

src/stubs/resource_template.stub

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,38 @@ DESC;
117117
// Optional path: 'file:///data{/type}{/subtype}/latest.json'
118118
// Multiple formats: 'api://export/{dataset}.{format}' where format = json|csv|xml
119119
}
120+
121+
/*
122+
* TESTING YOUR RESOURCE TEMPLATE:
123+
* ===============================
124+
*
125+
* 1. Register the template in config/mcp-server.php
126+
* 2. Test discovery:
127+
* curl -X POST http://localhost:8000/mcp \
128+
* -H "Content-Type: application/json" \
129+
* -d '{"jsonrpc":"2.0","id":1,"method":"resources/templates/list"}'
130+
*
131+
* 3. Test with specific URI:
132+
* curl -X POST http://localhost:8000/mcp \
133+
* -H "Content-Type: application/json" \
134+
* -d '{"jsonrpc":"2.0","id":2,"method":"resources/read","params":{"uri":"file:///{{ className|lower }}/123.json"}}'
135+
*
136+
* 4. Use MCP Inspector for interactive testing:
137+
* npx @modelcontextprotocol/inspector
138+
*
139+
* TROUBLESHOOTING:
140+
* ===============
141+
* - Verify your ResourceRepository can handle the generated URIs
142+
* - Check that variable substitution works correctly
143+
* - Ensure MIME types match your actual content
144+
* - Test edge cases (missing variables, invalid formats)
145+
* - Validate that LLMs can understand your variable documentation
146+
*
147+
* PERFORMANCE CONSIDERATIONS:
148+
* ==========================
149+
* - Cache expensive resource operations
150+
* - Implement rate limiting for complex queries
151+
* - Consider pagination for large datasets
152+
* - Optimize database queries used by your resources
153+
* - Monitor template usage patterns
154+
*/

0 commit comments

Comments
 (0)