A Streamlit-based application that generates personalized day-wise learning paths using MCP servers for YouTube, Google Drive, and Notion integration. Uses LangGraph agents to orchestrate learning path creation with AI.
Static source inference · medium confidence · evidence: Streamable HTTP
Current-spec patterns detected
Summary
This server exhibits critical deficiencies across all definition quality dimensions. Tool definitions are minimally specified with generic descriptions, missing parameter type information, and no output schema documentation. All 7 tools lack the depth required for reliable LLM invocation. The server is clearly a proof-of-concept rather than production-ready. Descriptions are generic and fail to specify what the tools actually return, what parameters control, or how to use them correctly. No input validation constraints are present, and error handling is completely absent from the definitions.
Tools (7)
drive_create_documentwriteauth
Create a new Google Drive document for the learning path
drive_write_documentwriteauth
Write or update content in a Google Drive document
notion_create_pagewriteauth
Create a new Notion page for the learning path
notion_write_pagewriteauth
Write or update content in a Notion page
youtube_playlist_add_videoswriteauth
Add selected videos to a YouTube playlist
youtube_playlist_createwriteauth
Create a public YouTube playlist with a relevant title for the learning path
youtube_searchread onlyauth
Search for YouTube videos relevant to learning topics and retrieve video URLs for the learning path
All tool descriptions are under 100 characters and lack actionable context. 'Search for YouTube videos relevant to learning topics' does not explain what the output is, when to call this tool vs. alternatives, or what format query should take. Descriptions must guide LLM selection and clarify expected outcomes.
No output schemas are documented. LLMs cannot plan downstream tool calls or extract data if they don't know what fields to expect. For example, youtube_search must specify whether it returns video_id, title, url, duration, channel_name, etc. The agent has no way to know which fields it can use in subsequent tool calls.
Expand tool descriptions to 100 - 200 characters, addressing: What does the tool return? When should the LLM call it instead of a similar tool? What are the prerequisites? Example: 'youtube_search: Searches YouTube for educational videos. Returns a list of videos with titles, URLs, channels, durations, and view counts. Use this first to discover relevant learning resources for a topic. Accepts natural language queries like "python basics for beginners."'
Document complete output schemas for all tools. For youtube_search, specify: [{video_id: string, title: string, url: string, channel_name: string, duration_seconds: number, view_count: number}, ...]. For create_playlist, return: {playlist_id: string, title: string, creation_timestamp: string}. For drive_create_document, return: {document_id: string, title: string, link: string}.
Add parameter constraints and guidance. For 'query' in youtube_search: 'A natural language search term (e.g., "beginner python", "machine learning"). Aim for 2 - 5 words. Avoid overly specific phrases; use broader topics for initial discovery.' For 'playlist_id' and 'video_id': 'YouTube resource ID (11-character alphanumeric string). Examples: dQw4w9WgXcQ (video), PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf (playlist).'
Add error recovery guidance. Example for youtube_search: 'If no results are found, try a broader topic or synonym. If rate limited, wait 60 seconds before retrying.' For drive_create_document: 'If quota exceeded, suggest archiving old documents. If permission denied, verify the user has write access to the target folder.'
Input parameters lack type definitions in the visible schema. The 'query' parameter in youtube_search shows type: 'string' but missing are: minimum/maximum length, regex patterns, examples of valid queries (e.g. 'beginner python' vs 'machine learning nlp cv'), and guidance on search scope. Similarly, 'playlist_id' and 'video_id' have no format constraints, are they YouTube's 34-char alphanumeric IDs? Can the LLM pass user-friendly names?
No error handling guidance. The definitions include no mention of what happens when youtube_search returns zero results, when playlist creation fails due to quota limits, or when a video_id is invalid. LLMs need recovery instructions: 'If youtube_search returns no results, try a broader query or suggest related topics.' Without this, agents get stuck on failures.
Credentials (API keys) are exposed as Streamlit text inputs in app.py (google_api_key, youtube_pipedream_url, drive_pipedream_url, notion_pipedream_url). These must never appear in tool parameters or UI inputs. Use environment variables or a secure vault. Storing secrets in Streamlit state risks logging them in traces.
No pagination or result-limiting guidance. youtube_search likely returns many results, but there's no mention of limit, offset, page_size, or max_results parameters. Large result sets waste tokens and risk context exhaustion. Baselines recommend capping results at 20 - 50 and documenting the limit in descriptions.
Write operations (youtube_create_playlist, youtube_add_to_playlist, drive_create_document, drive_update_document, notion_create_page, notion_update_page) lack idempotency guidance and confirmation mechanisms. If an agent retries youtube_create_playlist due to a transient network failure, does it create a duplicate playlist? Descriptions must clarify idempotency or recommend dry-run/confirmation patterns.
Tool chain dependencies are undocumented. youtube_create_playlist likely returns a playlist_id, which youtube_add_to_playlist needs. But the definitions don't specify this contract. Similarly, drive_create_document should return a document_id for drive_update_document to use. Without explicit chaining IDs in responses, agents waste lookup calls.
Naming overlaps risk LLM confusion. youtube_create_playlist, drive_create_document, and notion_create_page all begin with 'create_', but it's unclear whether they also populate content. The prompt.py 'Step 5' mentions 'Create a new document...Paste the formatted day-wise learning path content,' suggesting create_document may need to accept content as a parameter, but this is not documented. Ambiguous names cause incorrect tool selection.
drive_create_documentnotion_create_page
Implement environment-based secret injection. Remove google_api_key, youtube_pipedream_url, drive_pipedream_url, and notion_pipedream_url from Streamlit inputs. Load from .env or secure vault. Pass credentials server-side to utils.py without exposing them in tool parameters or logs.
Add pagination to youtube_search. Introduce max_results (default: 20, max: 50) and page_token parameters. Update description: 'Returns up to 20 videos by default. Use page_token for pagination or increase max_results (max 50) to fetch more.'
Clarify idempotency and add safe retry guidance. For youtube_create_playlist: 'Safe to retry on network errors. Creates one playlist per unique title; re-calling with the same title is safe and idempotent.' For write operations, consider adding an optional idempotency_key or exists_ok flag.
Document tool chaining requirements. youtube_create_playlist description should state: 'Returns playlist_id (required for youtube_add_to_playlist).' drive_create_document should state: 'Returns document_id (required for drive_update_document).' This enables the agent to pipe outputs between tools.
Rename ambiguous create_ tools to be specific. Consider: 'drive_create_and_populate_document' → split into drive_create_document (returns document_id) and drive_update_document (accepts document_id + content). Similarly, clarify whether notion_create_page auto-populates or returns a page_id for later update.
Add permission gates and audit trail guidance. Document what scopes each tool requires (e.g., youtube_add_to_playlist requires 'youtube.write'). Implement server-side logging to track who called what tool, with which parameters, at what time, and whether it succeeded. This enables compliance audits and incident response.
Validate all inputs early and return actionable error messages. Instead of generic failures, return: 'Invalid video_id: got "abc123". YouTube video IDs are 11-character alphanumeric strings. Example: dQw4w9WgXcQ.' This lets LLMs self-correct in one retry.
Add per-item success/failure reporting for batch operations. If youtube_add_to_playlist accepts multiple video_ids, return: [{video_id: string, status: 'success'|'failed', error?: string}, ...]. This lets agents retry only failed items, not the entire batch.