ai-parrot 0.17.2__cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
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.
- agentui/.prettierrc +15 -0
- agentui/QUICKSTART.md +272 -0
- agentui/README.md +59 -0
- agentui/env.example +16 -0
- agentui/jsconfig.json +14 -0
- agentui/package-lock.json +4242 -0
- agentui/package.json +34 -0
- agentui/scripts/postinstall/apply-patches.mjs +260 -0
- agentui/src/app.css +61 -0
- agentui/src/app.d.ts +13 -0
- agentui/src/app.html +12 -0
- agentui/src/components/LoadingSpinner.svelte +64 -0
- agentui/src/components/ThemeSwitcher.svelte +159 -0
- agentui/src/components/index.js +4 -0
- agentui/src/lib/api/bots.ts +60 -0
- agentui/src/lib/api/chat.ts +22 -0
- agentui/src/lib/api/http.ts +25 -0
- agentui/src/lib/components/BotCard.svelte +33 -0
- agentui/src/lib/components/ChatBubble.svelte +63 -0
- agentui/src/lib/components/Toast.svelte +21 -0
- agentui/src/lib/config.ts +20 -0
- agentui/src/lib/stores/auth.svelte.ts +73 -0
- agentui/src/lib/stores/theme.svelte.js +64 -0
- agentui/src/lib/stores/toast.svelte.ts +31 -0
- agentui/src/lib/utils/conversation.ts +39 -0
- agentui/src/routes/+layout.svelte +20 -0
- agentui/src/routes/+page.svelte +232 -0
- agentui/src/routes/login/+page.svelte +200 -0
- agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
- agentui/src/routes/talk/[agentId]/+page.ts +7 -0
- agentui/static/README.md +1 -0
- agentui/svelte.config.js +11 -0
- agentui/tailwind.config.ts +53 -0
- agentui/tsconfig.json +3 -0
- agentui/vite.config.ts +10 -0
- ai_parrot-0.17.2.dist-info/METADATA +472 -0
- ai_parrot-0.17.2.dist-info/RECORD +535 -0
- ai_parrot-0.17.2.dist-info/WHEEL +6 -0
- ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
- ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
- ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
- crew-builder/.prettierrc +15 -0
- crew-builder/QUICKSTART.md +259 -0
- crew-builder/README.md +113 -0
- crew-builder/env.example +17 -0
- crew-builder/jsconfig.json +14 -0
- crew-builder/package-lock.json +4182 -0
- crew-builder/package.json +37 -0
- crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
- crew-builder/src/app.css +62 -0
- crew-builder/src/app.d.ts +13 -0
- crew-builder/src/app.html +12 -0
- crew-builder/src/components/LoadingSpinner.svelte +64 -0
- crew-builder/src/components/ThemeSwitcher.svelte +149 -0
- crew-builder/src/components/index.js +9 -0
- crew-builder/src/lib/api/bots.ts +60 -0
- crew-builder/src/lib/api/chat.ts +80 -0
- crew-builder/src/lib/api/client.ts +56 -0
- crew-builder/src/lib/api/crew/crew.ts +136 -0
- crew-builder/src/lib/api/index.ts +5 -0
- crew-builder/src/lib/api/o365/auth.ts +65 -0
- crew-builder/src/lib/auth/auth.ts +54 -0
- crew-builder/src/lib/components/AgentNode.svelte +43 -0
- crew-builder/src/lib/components/BotCard.svelte +33 -0
- crew-builder/src/lib/components/ChatBubble.svelte +67 -0
- crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
- crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
- crew-builder/src/lib/components/JsonViewer.svelte +24 -0
- crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
- crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
- crew-builder/src/lib/components/Toast.svelte +67 -0
- crew-builder/src/lib/components/Toolbar.svelte +157 -0
- crew-builder/src/lib/components/index.ts +10 -0
- crew-builder/src/lib/config.ts +8 -0
- crew-builder/src/lib/stores/auth.svelte.ts +228 -0
- crew-builder/src/lib/stores/crewStore.ts +369 -0
- crew-builder/src/lib/stores/theme.svelte.js +145 -0
- crew-builder/src/lib/stores/toast.svelte.ts +69 -0
- crew-builder/src/lib/utils/conversation.ts +39 -0
- crew-builder/src/lib/utils/markdown.ts +122 -0
- crew-builder/src/lib/utils/talkHistory.ts +47 -0
- crew-builder/src/routes/+layout.svelte +20 -0
- crew-builder/src/routes/+page.svelte +539 -0
- crew-builder/src/routes/agents/+page.svelte +247 -0
- crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
- crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
- crew-builder/src/routes/builder/+page.svelte +204 -0
- crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
- crew-builder/src/routes/crew/ask/+page.ts +1 -0
- crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
- crew-builder/src/routes/login/+page.svelte +197 -0
- crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
- crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
- crew-builder/static/README.md +1 -0
- crew-builder/svelte.config.js +11 -0
- crew-builder/tailwind.config.ts +53 -0
- crew-builder/tsconfig.json +3 -0
- crew-builder/vite.config.ts +10 -0
- mcp_servers/calculator_server.py +309 -0
- parrot/__init__.py +27 -0
- parrot/__pycache__/__init__.cpython-310.pyc +0 -0
- parrot/__pycache__/version.cpython-310.pyc +0 -0
- parrot/_version.py +34 -0
- parrot/a2a/__init__.py +48 -0
- parrot/a2a/client.py +658 -0
- parrot/a2a/discovery.py +89 -0
- parrot/a2a/mixin.py +257 -0
- parrot/a2a/models.py +376 -0
- parrot/a2a/server.py +770 -0
- parrot/agents/__init__.py +29 -0
- parrot/bots/__init__.py +12 -0
- parrot/bots/a2a_agent.py +19 -0
- parrot/bots/abstract.py +3139 -0
- parrot/bots/agent.py +1129 -0
- parrot/bots/basic.py +9 -0
- parrot/bots/chatbot.py +669 -0
- parrot/bots/data.py +1618 -0
- parrot/bots/database/__init__.py +5 -0
- parrot/bots/database/abstract.py +3071 -0
- parrot/bots/database/cache.py +286 -0
- parrot/bots/database/models.py +468 -0
- parrot/bots/database/prompts.py +154 -0
- parrot/bots/database/retries.py +98 -0
- parrot/bots/database/router.py +269 -0
- parrot/bots/database/sql.py +41 -0
- parrot/bots/db/__init__.py +6 -0
- parrot/bots/db/abstract.py +556 -0
- parrot/bots/db/bigquery.py +602 -0
- parrot/bots/db/cache.py +85 -0
- parrot/bots/db/documentdb.py +668 -0
- parrot/bots/db/elastic.py +1014 -0
- parrot/bots/db/influx.py +898 -0
- parrot/bots/db/mock.py +96 -0
- parrot/bots/db/multi.py +783 -0
- parrot/bots/db/prompts.py +185 -0
- parrot/bots/db/sql.py +1255 -0
- parrot/bots/db/tools.py +212 -0
- parrot/bots/document.py +680 -0
- parrot/bots/hrbot.py +15 -0
- parrot/bots/kb.py +170 -0
- parrot/bots/mcp.py +36 -0
- parrot/bots/orchestration/README.md +463 -0
- parrot/bots/orchestration/__init__.py +1 -0
- parrot/bots/orchestration/agent.py +155 -0
- parrot/bots/orchestration/crew.py +3330 -0
- parrot/bots/orchestration/fsm.py +1179 -0
- parrot/bots/orchestration/hr.py +434 -0
- parrot/bots/orchestration/storage/__init__.py +4 -0
- parrot/bots/orchestration/storage/memory.py +100 -0
- parrot/bots/orchestration/storage/mixin.py +119 -0
- parrot/bots/orchestration/verify.py +202 -0
- parrot/bots/product.py +204 -0
- parrot/bots/prompts/__init__.py +96 -0
- parrot/bots/prompts/agents.py +155 -0
- parrot/bots/prompts/data.py +216 -0
- parrot/bots/prompts/output_generation.py +8 -0
- parrot/bots/scraper/__init__.py +3 -0
- parrot/bots/scraper/models.py +122 -0
- parrot/bots/scraper/scraper.py +1173 -0
- parrot/bots/scraper/templates.py +115 -0
- parrot/bots/stores/__init__.py +5 -0
- parrot/bots/stores/local.py +172 -0
- parrot/bots/webdev.py +81 -0
- parrot/cli.py +17 -0
- parrot/clients/__init__.py +16 -0
- parrot/clients/base.py +1491 -0
- parrot/clients/claude.py +1191 -0
- parrot/clients/factory.py +129 -0
- parrot/clients/google.py +4567 -0
- parrot/clients/gpt.py +1975 -0
- parrot/clients/grok.py +432 -0
- parrot/clients/groq.py +986 -0
- parrot/clients/hf.py +582 -0
- parrot/clients/models.py +18 -0
- parrot/conf.py +395 -0
- parrot/embeddings/__init__.py +9 -0
- parrot/embeddings/base.py +157 -0
- parrot/embeddings/google.py +98 -0
- parrot/embeddings/huggingface.py +74 -0
- parrot/embeddings/openai.py +84 -0
- parrot/embeddings/processor.py +88 -0
- parrot/exceptions.c +13868 -0
- parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/exceptions.pxd +22 -0
- parrot/exceptions.pxi +15 -0
- parrot/exceptions.pyx +44 -0
- parrot/generators/__init__.py +29 -0
- parrot/generators/base.py +200 -0
- parrot/generators/html.py +293 -0
- parrot/generators/react.py +205 -0
- parrot/generators/streamlit.py +203 -0
- parrot/generators/template.py +105 -0
- parrot/handlers/__init__.py +4 -0
- parrot/handlers/agent.py +861 -0
- parrot/handlers/agents/__init__.py +1 -0
- parrot/handlers/agents/abstract.py +900 -0
- parrot/handlers/bots.py +338 -0
- parrot/handlers/chat.py +915 -0
- parrot/handlers/creation.sql +192 -0
- parrot/handlers/crew/ARCHITECTURE.md +362 -0
- parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
- parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
- parrot/handlers/crew/__init__.py +0 -0
- parrot/handlers/crew/handler.py +801 -0
- parrot/handlers/crew/models.py +229 -0
- parrot/handlers/crew/redis_persistence.py +523 -0
- parrot/handlers/jobs/__init__.py +10 -0
- parrot/handlers/jobs/job.py +384 -0
- parrot/handlers/jobs/mixin.py +627 -0
- parrot/handlers/jobs/models.py +115 -0
- parrot/handlers/jobs/worker.py +31 -0
- parrot/handlers/models.py +596 -0
- parrot/handlers/o365_auth.py +105 -0
- parrot/handlers/stream.py +337 -0
- parrot/interfaces/__init__.py +6 -0
- parrot/interfaces/aws.py +143 -0
- parrot/interfaces/credentials.py +113 -0
- parrot/interfaces/database.py +27 -0
- parrot/interfaces/google.py +1123 -0
- parrot/interfaces/hierarchy.py +1227 -0
- parrot/interfaces/http.py +651 -0
- parrot/interfaces/images/__init__.py +0 -0
- parrot/interfaces/images/plugins/__init__.py +24 -0
- parrot/interfaces/images/plugins/abstract.py +58 -0
- parrot/interfaces/images/plugins/analisys.py +148 -0
- parrot/interfaces/images/plugins/classify.py +150 -0
- parrot/interfaces/images/plugins/classifybase.py +182 -0
- parrot/interfaces/images/plugins/detect.py +150 -0
- parrot/interfaces/images/plugins/exif.py +1103 -0
- parrot/interfaces/images/plugins/hash.py +52 -0
- parrot/interfaces/images/plugins/vision.py +104 -0
- parrot/interfaces/images/plugins/yolo.py +66 -0
- parrot/interfaces/images/plugins/zerodetect.py +197 -0
- parrot/interfaces/o365.py +978 -0
- parrot/interfaces/onedrive.py +822 -0
- parrot/interfaces/sharepoint.py +1435 -0
- parrot/interfaces/soap.py +257 -0
- parrot/loaders/__init__.py +8 -0
- parrot/loaders/abstract.py +1131 -0
- parrot/loaders/audio.py +199 -0
- parrot/loaders/basepdf.py +53 -0
- parrot/loaders/basevideo.py +1568 -0
- parrot/loaders/csv.py +409 -0
- parrot/loaders/docx.py +116 -0
- parrot/loaders/epubloader.py +316 -0
- parrot/loaders/excel.py +199 -0
- parrot/loaders/factory.py +55 -0
- parrot/loaders/files/__init__.py +0 -0
- parrot/loaders/files/abstract.py +39 -0
- parrot/loaders/files/html.py +26 -0
- parrot/loaders/files/text.py +63 -0
- parrot/loaders/html.py +152 -0
- parrot/loaders/markdown.py +442 -0
- parrot/loaders/pdf.py +373 -0
- parrot/loaders/pdfmark.py +320 -0
- parrot/loaders/pdftables.py +506 -0
- parrot/loaders/ppt.py +476 -0
- parrot/loaders/qa.py +63 -0
- parrot/loaders/splitters/__init__.py +10 -0
- parrot/loaders/splitters/base.py +138 -0
- parrot/loaders/splitters/md.py +228 -0
- parrot/loaders/splitters/token.py +143 -0
- parrot/loaders/txt.py +26 -0
- parrot/loaders/video.py +89 -0
- parrot/loaders/videolocal.py +218 -0
- parrot/loaders/videounderstanding.py +377 -0
- parrot/loaders/vimeo.py +167 -0
- parrot/loaders/web.py +599 -0
- parrot/loaders/youtube.py +504 -0
- parrot/manager/__init__.py +5 -0
- parrot/manager/manager.py +1030 -0
- parrot/mcp/__init__.py +28 -0
- parrot/mcp/adapter.py +105 -0
- parrot/mcp/cli.py +174 -0
- parrot/mcp/client.py +119 -0
- parrot/mcp/config.py +75 -0
- parrot/mcp/integration.py +842 -0
- parrot/mcp/oauth.py +933 -0
- parrot/mcp/server.py +225 -0
- parrot/mcp/transports/__init__.py +3 -0
- parrot/mcp/transports/base.py +279 -0
- parrot/mcp/transports/grpc_session.py +163 -0
- parrot/mcp/transports/http.py +312 -0
- parrot/mcp/transports/mcp.proto +108 -0
- parrot/mcp/transports/quic.py +1082 -0
- parrot/mcp/transports/sse.py +330 -0
- parrot/mcp/transports/stdio.py +309 -0
- parrot/mcp/transports/unix.py +395 -0
- parrot/mcp/transports/websocket.py +547 -0
- parrot/memory/__init__.py +16 -0
- parrot/memory/abstract.py +209 -0
- parrot/memory/agent.py +32 -0
- parrot/memory/cache.py +175 -0
- parrot/memory/core.py +555 -0
- parrot/memory/file.py +153 -0
- parrot/memory/mem.py +131 -0
- parrot/memory/redis.py +613 -0
- parrot/models/__init__.py +46 -0
- parrot/models/basic.py +118 -0
- parrot/models/compliance.py +208 -0
- parrot/models/crew.py +395 -0
- parrot/models/detections.py +654 -0
- parrot/models/generation.py +85 -0
- parrot/models/google.py +223 -0
- parrot/models/groq.py +23 -0
- parrot/models/openai.py +30 -0
- parrot/models/outputs.py +285 -0
- parrot/models/responses.py +938 -0
- parrot/notifications/__init__.py +743 -0
- parrot/openapi/__init__.py +3 -0
- parrot/openapi/components.yaml +641 -0
- parrot/openapi/config.py +322 -0
- parrot/outputs/__init__.py +32 -0
- parrot/outputs/formats/__init__.py +108 -0
- parrot/outputs/formats/altair.py +359 -0
- parrot/outputs/formats/application.py +122 -0
- parrot/outputs/formats/base.py +351 -0
- parrot/outputs/formats/bokeh.py +356 -0
- parrot/outputs/formats/card.py +424 -0
- parrot/outputs/formats/chart.py +436 -0
- parrot/outputs/formats/d3.py +255 -0
- parrot/outputs/formats/echarts.py +310 -0
- parrot/outputs/formats/generators/__init__.py +0 -0
- parrot/outputs/formats/generators/abstract.py +61 -0
- parrot/outputs/formats/generators/panel.py +145 -0
- parrot/outputs/formats/generators/streamlit.py +86 -0
- parrot/outputs/formats/generators/terminal.py +63 -0
- parrot/outputs/formats/holoviews.py +310 -0
- parrot/outputs/formats/html.py +147 -0
- parrot/outputs/formats/jinja2.py +46 -0
- parrot/outputs/formats/json.py +87 -0
- parrot/outputs/formats/map.py +933 -0
- parrot/outputs/formats/markdown.py +172 -0
- parrot/outputs/formats/matplotlib.py +237 -0
- parrot/outputs/formats/mixins/__init__.py +0 -0
- parrot/outputs/formats/mixins/emaps.py +855 -0
- parrot/outputs/formats/plotly.py +341 -0
- parrot/outputs/formats/seaborn.py +310 -0
- parrot/outputs/formats/table.py +397 -0
- parrot/outputs/formats/template_report.py +138 -0
- parrot/outputs/formats/yaml.py +125 -0
- parrot/outputs/formatter.py +152 -0
- parrot/outputs/templates/__init__.py +95 -0
- parrot/pipelines/__init__.py +0 -0
- parrot/pipelines/abstract.py +210 -0
- parrot/pipelines/detector.py +124 -0
- parrot/pipelines/models.py +90 -0
- parrot/pipelines/planogram.py +3002 -0
- parrot/pipelines/table.sql +97 -0
- parrot/plugins/__init__.py +106 -0
- parrot/plugins/importer.py +80 -0
- parrot/py.typed +0 -0
- parrot/registry/__init__.py +18 -0
- parrot/registry/registry.py +594 -0
- parrot/scheduler/__init__.py +1189 -0
- parrot/scheduler/models.py +60 -0
- parrot/security/__init__.py +16 -0
- parrot/security/prompt_injection.py +268 -0
- parrot/security/security_events.sql +25 -0
- parrot/services/__init__.py +1 -0
- parrot/services/mcp/__init__.py +8 -0
- parrot/services/mcp/config.py +13 -0
- parrot/services/mcp/server.py +295 -0
- parrot/services/o365_remote_auth.py +235 -0
- parrot/stores/__init__.py +7 -0
- parrot/stores/abstract.py +352 -0
- parrot/stores/arango.py +1090 -0
- parrot/stores/bigquery.py +1377 -0
- parrot/stores/cache.py +106 -0
- parrot/stores/empty.py +10 -0
- parrot/stores/faiss_store.py +1157 -0
- parrot/stores/kb/__init__.py +9 -0
- parrot/stores/kb/abstract.py +68 -0
- parrot/stores/kb/cache.py +165 -0
- parrot/stores/kb/doc.py +325 -0
- parrot/stores/kb/hierarchy.py +346 -0
- parrot/stores/kb/local.py +457 -0
- parrot/stores/kb/prompt.py +28 -0
- parrot/stores/kb/redis.py +659 -0
- parrot/stores/kb/store.py +115 -0
- parrot/stores/kb/user.py +374 -0
- parrot/stores/models.py +59 -0
- parrot/stores/pgvector.py +3 -0
- parrot/stores/postgres.py +2853 -0
- parrot/stores/utils/__init__.py +0 -0
- parrot/stores/utils/chunking.py +197 -0
- parrot/telemetry/__init__.py +3 -0
- parrot/telemetry/mixin.py +111 -0
- parrot/template/__init__.py +3 -0
- parrot/template/engine.py +259 -0
- parrot/tools/__init__.py +23 -0
- parrot/tools/abstract.py +644 -0
- parrot/tools/agent.py +363 -0
- parrot/tools/arangodbsearch.py +537 -0
- parrot/tools/arxiv_tool.py +188 -0
- parrot/tools/calculator/__init__.py +3 -0
- parrot/tools/calculator/operations/__init__.py +38 -0
- parrot/tools/calculator/operations/calculus.py +80 -0
- parrot/tools/calculator/operations/statistics.py +76 -0
- parrot/tools/calculator/tool.py +150 -0
- parrot/tools/cloudwatch.py +988 -0
- parrot/tools/codeinterpreter/__init__.py +127 -0
- parrot/tools/codeinterpreter/executor.py +371 -0
- parrot/tools/codeinterpreter/internals.py +473 -0
- parrot/tools/codeinterpreter/models.py +643 -0
- parrot/tools/codeinterpreter/prompts.py +224 -0
- parrot/tools/codeinterpreter/tool.py +664 -0
- parrot/tools/company_info/__init__.py +6 -0
- parrot/tools/company_info/tool.py +1138 -0
- parrot/tools/correlationanalysis.py +437 -0
- parrot/tools/database/abstract.py +286 -0
- parrot/tools/database/bq.py +115 -0
- parrot/tools/database/cache.py +284 -0
- parrot/tools/database/models.py +95 -0
- parrot/tools/database/pg.py +343 -0
- parrot/tools/databasequery.py +1159 -0
- parrot/tools/db.py +1800 -0
- parrot/tools/ddgo.py +370 -0
- parrot/tools/decorators.py +271 -0
- parrot/tools/dftohtml.py +282 -0
- parrot/tools/document.py +549 -0
- parrot/tools/ecs.py +819 -0
- parrot/tools/edareport.py +368 -0
- parrot/tools/elasticsearch.py +1049 -0
- parrot/tools/employees.py +462 -0
- parrot/tools/epson/__init__.py +96 -0
- parrot/tools/excel.py +683 -0
- parrot/tools/file/__init__.py +13 -0
- parrot/tools/file/abstract.py +76 -0
- parrot/tools/file/gcs.py +378 -0
- parrot/tools/file/local.py +284 -0
- parrot/tools/file/s3.py +511 -0
- parrot/tools/file/tmp.py +309 -0
- parrot/tools/file/tool.py +501 -0
- parrot/tools/file_reader.py +129 -0
- parrot/tools/flowtask/__init__.py +19 -0
- parrot/tools/flowtask/tool.py +761 -0
- parrot/tools/gittoolkit.py +508 -0
- parrot/tools/google/__init__.py +18 -0
- parrot/tools/google/base.py +169 -0
- parrot/tools/google/tools.py +1251 -0
- parrot/tools/googlelocation.py +5 -0
- parrot/tools/googleroutes.py +5 -0
- parrot/tools/googlesearch.py +5 -0
- parrot/tools/googlesitesearch.py +5 -0
- parrot/tools/googlevoice.py +2 -0
- parrot/tools/gvoice.py +695 -0
- parrot/tools/ibisworld/README.md +225 -0
- parrot/tools/ibisworld/__init__.py +11 -0
- parrot/tools/ibisworld/tool.py +366 -0
- parrot/tools/jiratoolkit.py +1718 -0
- parrot/tools/manager.py +1098 -0
- parrot/tools/math.py +152 -0
- parrot/tools/metadata.py +476 -0
- parrot/tools/msteams.py +1621 -0
- parrot/tools/msword.py +635 -0
- parrot/tools/multidb.py +580 -0
- parrot/tools/multistoresearch.py +369 -0
- parrot/tools/networkninja.py +167 -0
- parrot/tools/nextstop/__init__.py +4 -0
- parrot/tools/nextstop/base.py +286 -0
- parrot/tools/nextstop/employee.py +733 -0
- parrot/tools/nextstop/store.py +462 -0
- parrot/tools/notification.py +435 -0
- parrot/tools/o365/__init__.py +42 -0
- parrot/tools/o365/base.py +295 -0
- parrot/tools/o365/bundle.py +522 -0
- parrot/tools/o365/events.py +554 -0
- parrot/tools/o365/mail.py +992 -0
- parrot/tools/o365/onedrive.py +497 -0
- parrot/tools/o365/sharepoint.py +641 -0
- parrot/tools/openapi_toolkit.py +904 -0
- parrot/tools/openweather.py +527 -0
- parrot/tools/pdfprint.py +1001 -0
- parrot/tools/powerbi.py +518 -0
- parrot/tools/powerpoint.py +1113 -0
- parrot/tools/pricestool.py +146 -0
- parrot/tools/products/__init__.py +246 -0
- parrot/tools/prophet_tool.py +171 -0
- parrot/tools/pythonpandas.py +630 -0
- parrot/tools/pythonrepl.py +910 -0
- parrot/tools/qsource.py +436 -0
- parrot/tools/querytoolkit.py +395 -0
- parrot/tools/quickeda.py +827 -0
- parrot/tools/resttool.py +553 -0
- parrot/tools/retail/__init__.py +0 -0
- parrot/tools/retail/bby.py +528 -0
- parrot/tools/sandboxtool.py +703 -0
- parrot/tools/sassie/__init__.py +352 -0
- parrot/tools/scraping/__init__.py +7 -0
- parrot/tools/scraping/docs/select.md +466 -0
- parrot/tools/scraping/documentation.md +1278 -0
- parrot/tools/scraping/driver.py +436 -0
- parrot/tools/scraping/models.py +576 -0
- parrot/tools/scraping/options.py +85 -0
- parrot/tools/scraping/orchestrator.py +517 -0
- parrot/tools/scraping/readme.md +740 -0
- parrot/tools/scraping/tool.py +3115 -0
- parrot/tools/seasonaldetection.py +642 -0
- parrot/tools/shell_tool/__init__.py +5 -0
- parrot/tools/shell_tool/actions.py +408 -0
- parrot/tools/shell_tool/engine.py +155 -0
- parrot/tools/shell_tool/models.py +322 -0
- parrot/tools/shell_tool/tool.py +442 -0
- parrot/tools/site_search.py +214 -0
- parrot/tools/textfile.py +418 -0
- parrot/tools/think.py +378 -0
- parrot/tools/toolkit.py +298 -0
- parrot/tools/webapp_tool.py +187 -0
- parrot/tools/whatif.py +1279 -0
- parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
- parrot/tools/workday/__init__.py +6 -0
- parrot/tools/workday/models.py +1389 -0
- parrot/tools/workday/tool.py +1293 -0
- parrot/tools/yfinance_tool.py +306 -0
- parrot/tools/zipcode.py +217 -0
- parrot/utils/__init__.py +2 -0
- parrot/utils/helpers.py +73 -0
- parrot/utils/parsers/__init__.py +5 -0
- parrot/utils/parsers/toml.c +12078 -0
- parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/parsers/toml.pyx +21 -0
- parrot/utils/toml.py +11 -0
- parrot/utils/types.cpp +20936 -0
- parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/types.pyx +213 -0
- parrot/utils/uv.py +11 -0
- parrot/version.py +10 -0
- parrot/yaml-rs/Cargo.lock +350 -0
- parrot/yaml-rs/Cargo.toml +19 -0
- parrot/yaml-rs/pyproject.toml +19 -0
- parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
- parrot/yaml-rs/src/lib.rs +222 -0
- requirements/docker-compose.yml +24 -0
- requirements/requirements-dev.txt +21 -0
parrot/mcp/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""MCP integration for AI-Parrot."""
|
|
2
|
+
|
|
3
|
+
from .integration import (
|
|
4
|
+
MCPEnabledMixin,
|
|
5
|
+
MCPServerConfig,
|
|
6
|
+
MCPToolManager,
|
|
7
|
+
MCPClient,
|
|
8
|
+
create_local_mcp_server,
|
|
9
|
+
create_http_mcp_server,
|
|
10
|
+
create_api_key_mcp_server,
|
|
11
|
+
)
|
|
12
|
+
from .config import AuthMethod
|
|
13
|
+
from .oauth import APIKeyStore, ExternalOAuthValidator, APIKeyRecord
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"MCPEnabledMixin",
|
|
17
|
+
"MCPServerConfig",
|
|
18
|
+
"MCPToolManager",
|
|
19
|
+
"MCPClient",
|
|
20
|
+
"create_local_mcp_server",
|
|
21
|
+
"create_http_mcp_server",
|
|
22
|
+
"create_api_key_mcp_server",
|
|
23
|
+
"AuthMethod",
|
|
24
|
+
"APIKeyStore",
|
|
25
|
+
"ExternalOAuthValidator",
|
|
26
|
+
"APIKeyRecord",
|
|
27
|
+
]
|
|
28
|
+
|
parrot/mcp/adapter.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import json
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
from parrot.tools.abstract import AbstractTool, ToolResult
|
|
6
|
+
|
|
7
|
+
class MCPToolAdapter:
|
|
8
|
+
"""Adapts AI-Parrot AbstractTool to MCP tool format."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, tool: AbstractTool):
|
|
11
|
+
self.tool = tool
|
|
12
|
+
self.logger = logging.getLogger(f"MCPToolAdapter.{tool.name}")
|
|
13
|
+
|
|
14
|
+
def to_mcp_tool_definition(self) -> Dict[str, Any]:
|
|
15
|
+
"""Convert AbstractTool to MCP tool definition."""
|
|
16
|
+
# Extract schema from the tool's args_schema
|
|
17
|
+
input_schema = {}
|
|
18
|
+
if hasattr(self.tool, 'args_schema') and self.tool.args_schema:
|
|
19
|
+
try:
|
|
20
|
+
# Get the JSON schema from the Pydantic model
|
|
21
|
+
input_schema = self.tool.args_schema.model_json_schema()
|
|
22
|
+
except Exception as e:
|
|
23
|
+
self.logger.warning(f"Could not extract schema for {self.tool.name}: {e}")
|
|
24
|
+
input_schema = {"type": "object", "properties": {}}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
"name": self.tool.name or "unknown_tool",
|
|
28
|
+
"description": self.tool.description or f"Tool: {self.tool.name}",
|
|
29
|
+
"inputSchema": input_schema
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
33
|
+
"""Execute the AI-Parrot tool and convert result to MCP format."""
|
|
34
|
+
try:
|
|
35
|
+
# Execute the tool
|
|
36
|
+
result = await self.tool._execute(**arguments)
|
|
37
|
+
|
|
38
|
+
# Convert ToolResult to MCP response format
|
|
39
|
+
if isinstance(result, ToolResult):
|
|
40
|
+
return self._toolresult_to_mcp(result)
|
|
41
|
+
else:
|
|
42
|
+
# Handle direct results (for backward compatibility)
|
|
43
|
+
return {
|
|
44
|
+
"content": [
|
|
45
|
+
{
|
|
46
|
+
"type": "text",
|
|
47
|
+
"text": str(result)
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"isError": False
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
except Exception as e:
|
|
54
|
+
self.logger.error(f"Tool execution failed: {e}")
|
|
55
|
+
return {
|
|
56
|
+
"content": [
|
|
57
|
+
{
|
|
58
|
+
"type": "text",
|
|
59
|
+
"text": f"Error executing tool: {str(e)}"
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"isError": True
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
def _toolresult_to_mcp(self, result: ToolResult) -> Dict[str, Any]:
|
|
66
|
+
"""Convert ToolResult to MCP response format."""
|
|
67
|
+
content_items = []
|
|
68
|
+
|
|
69
|
+
if result.status == "success":
|
|
70
|
+
# Handle different result types
|
|
71
|
+
if isinstance(result.result, str):
|
|
72
|
+
content_items.append({
|
|
73
|
+
"type": "text",
|
|
74
|
+
"text": result.result
|
|
75
|
+
})
|
|
76
|
+
elif isinstance(result.result, dict):
|
|
77
|
+
content_items.append({
|
|
78
|
+
"type": "text",
|
|
79
|
+
"text": json.dumps(result.result, indent=2, default=str)
|
|
80
|
+
})
|
|
81
|
+
else:
|
|
82
|
+
content_items.append({
|
|
83
|
+
"type": "text",
|
|
84
|
+
"text": str(result.result)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
# Add metadata if present
|
|
88
|
+
if result.metadata:
|
|
89
|
+
content_items.append({
|
|
90
|
+
"type": "text",
|
|
91
|
+
"text": f"\nMetadata: {json.dumps(result.metadata, indent=2, default=str)}"
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
else:
|
|
95
|
+
# Handle error case
|
|
96
|
+
error_text = result.error or "Unknown error occurred"
|
|
97
|
+
content_items.append({
|
|
98
|
+
"type": "text",
|
|
99
|
+
"text": f"Error: {error_text}"
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
"content": content_items,
|
|
104
|
+
"isError": result.status != "success"
|
|
105
|
+
}
|
parrot/mcp/cli.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import sys
|
|
3
|
+
import importlib.util
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
import yaml
|
|
8
|
+
import click
|
|
9
|
+
from navconfig.logging import logging
|
|
10
|
+
from .server import MCPServer, MCPServerConfig
|
|
11
|
+
from ..tools.abstract import AbstractTool
|
|
12
|
+
from ..tools.toolkit import AbstractToolkit
|
|
13
|
+
from ..services.mcp.server import ParrotMCPServer, TransportConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group()
|
|
17
|
+
def mcp():
|
|
18
|
+
"""MCP server commands."""
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@mcp.command()
|
|
23
|
+
@click.argument('config_file', type=click.Path(exists=True))
|
|
24
|
+
@click.option(
|
|
25
|
+
'--transport', type=click.Choice(['stdio', 'unix', 'http']), default=None,
|
|
26
|
+
help='Override transport from config')
|
|
27
|
+
@click.option(
|
|
28
|
+
'--socket', type=str, default=None,
|
|
29
|
+
help='Unix socket path (for unix transport)')
|
|
30
|
+
@click.option(
|
|
31
|
+
'--port', type=int, default=None,
|
|
32
|
+
help='Port (for http transport)')
|
|
33
|
+
@click.option(
|
|
34
|
+
'--log-level', type=str, default='INFO',
|
|
35
|
+
help='Logging level')
|
|
36
|
+
def serve(
|
|
37
|
+
config_file: str, transport: Optional[str], socket: Optional[str],
|
|
38
|
+
port: Optional[int], log_level: str):
|
|
39
|
+
"""
|
|
40
|
+
Start an MCP server from a Python config file or YAML.
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
|
|
44
|
+
# Python config file
|
|
45
|
+
parrot mcp serve workday_server.py --transport unix --socket /tmp/workday.sock
|
|
46
|
+
|
|
47
|
+
# YAML config file
|
|
48
|
+
parrot mcp serve mcp_config.yaml
|
|
49
|
+
|
|
50
|
+
Python config file should define 'mcp' variable:
|
|
51
|
+
|
|
52
|
+
# workday_server.py
|
|
53
|
+
from parrot.services import ParrotMCPServer
|
|
54
|
+
from parrot.toolkits.workday import WorkdayToolkit
|
|
55
|
+
|
|
56
|
+
mcp = ParrotMCPServer(
|
|
57
|
+
name="workday-mcp",
|
|
58
|
+
tools=WorkdayToolkit(redis_url="redis://localhost:6379/4")
|
|
59
|
+
)
|
|
60
|
+
"""
|
|
61
|
+
config_path = Path(config_file)
|
|
62
|
+
|
|
63
|
+
if config_path.suffix in {'.yaml', '.yml'}:
|
|
64
|
+
mcp_server = _load_from_yaml(config_path)
|
|
65
|
+
elif config_path.suffix == '.py':
|
|
66
|
+
mcp_server = _load_from_python(config_path)
|
|
67
|
+
else:
|
|
68
|
+
click.echo(f"Error: Unsupported config file type: {config_path.suffix}", err=True)
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
# Override settings from CLI
|
|
72
|
+
if transport:
|
|
73
|
+
# Need to update transport config
|
|
74
|
+
mcp_server.transport_configs = {
|
|
75
|
+
transport: _create_transport_config(transport, socket, port)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Set log level
|
|
79
|
+
logging.getLogger().setLevel(log_level)
|
|
80
|
+
|
|
81
|
+
# Run the server
|
|
82
|
+
asyncio.run(_run_standalone_server(mcp_server))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _load_from_python(config_path: Path) -> 'ParrotMCPServer':
|
|
86
|
+
"""Load ParrotMCPServer from Python file."""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
spec = importlib.util.spec_from_file_location("mcp_config", config_path)
|
|
90
|
+
module = importlib.util.module_from_spec(spec)
|
|
91
|
+
spec.loader.exec_module(module)
|
|
92
|
+
|
|
93
|
+
if not hasattr(module, 'mcp'):
|
|
94
|
+
raise ValueError(
|
|
95
|
+
f"Config file {config_path} must define 'mcp' variable "
|
|
96
|
+
"containing a ParrotMCPServer instance"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return module.mcp
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _load_from_yaml(config_path: Path) -> ParrotMCPServer:
|
|
103
|
+
"""Load ParrotMCPServer from YAML file."""
|
|
104
|
+
with open(config_path) as f:
|
|
105
|
+
config = yaml.safe_load(f)
|
|
106
|
+
|
|
107
|
+
# Parse tools from YAML
|
|
108
|
+
tools_config = {
|
|
109
|
+
tool_entry['class']: tool_entry['module']
|
|
110
|
+
for tool_entry in config.get('tools', [])
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Parse transports
|
|
114
|
+
transports = config.get('transport', 'stdio')
|
|
115
|
+
|
|
116
|
+
return ParrotMCPServer(
|
|
117
|
+
name=config.get('name', 'ai-parrot-mcp'),
|
|
118
|
+
description=config.get('description', 'AI-Parrot MCP Server'),
|
|
119
|
+
transports=transports,
|
|
120
|
+
tools=tools_config,
|
|
121
|
+
**config.get('server_config', {})
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _create_transport_config(transport: str, socket: Optional[str], port: Optional[int]):
|
|
126
|
+
"""Create TransportConfig from CLI args."""
|
|
127
|
+
return TransportConfig(
|
|
128
|
+
transport=transport,
|
|
129
|
+
host="127.0.0.1" if transport == "http" else None,
|
|
130
|
+
port=port if transport == "http" else None,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
async def _run_standalone_server(mcp_server: ParrotMCPServer):
|
|
135
|
+
"""Run MCP server in standalone mode (no aiohttp app)."""
|
|
136
|
+
logger = logging.getLogger("parrot.mcp.serve")
|
|
137
|
+
|
|
138
|
+
# Load tools
|
|
139
|
+
tools = await mcp_server._load_configured_tools()
|
|
140
|
+
if not tools:
|
|
141
|
+
logger.error("No tools configured")
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
|
|
144
|
+
logger.info(f"Loaded {len(tools)} tools")
|
|
145
|
+
|
|
146
|
+
# Get transport config (should be single transport in CLI mode)
|
|
147
|
+
if len(mcp_server.transport_configs) != 1:
|
|
148
|
+
logger.error("CLI mode requires exactly one transport")
|
|
149
|
+
sys.exit(1)
|
|
150
|
+
|
|
151
|
+
transport_key, transport_config = list(mcp_server.transport_configs.items())[0]
|
|
152
|
+
|
|
153
|
+
# Create MCP server
|
|
154
|
+
config = MCPServerConfig(
|
|
155
|
+
name=mcp_server.name,
|
|
156
|
+
description=mcp_server.description,
|
|
157
|
+
transport=transport_config.transport,
|
|
158
|
+
host=transport_config.host,
|
|
159
|
+
port=transport_config.port,
|
|
160
|
+
socket_path=transport_config.socket_path if hasattr(transport_config, 'socket_path') else None,
|
|
161
|
+
log_level=mcp_server.log_level,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
server = MCPServer(config)
|
|
165
|
+
server.register_tools(tools)
|
|
166
|
+
|
|
167
|
+
# Start and run
|
|
168
|
+
try:
|
|
169
|
+
logger.info(f"Starting MCP server in {transport_config.transport} mode...")
|
|
170
|
+
await server.start()
|
|
171
|
+
except KeyboardInterrupt:
|
|
172
|
+
logger.info("Interrupted by user")
|
|
173
|
+
finally:
|
|
174
|
+
await server.stop()
|
parrot/mcp/client.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import base64
|
|
3
|
+
import logging
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Dict, Any, Optional, List, Callable
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class MCPClientConfig:
|
|
9
|
+
"""Complete configuration for external MCP server connection."""
|
|
10
|
+
name: str
|
|
11
|
+
|
|
12
|
+
# Connection parameters
|
|
13
|
+
url: Optional[str] = None # For HTTP/SSE servers
|
|
14
|
+
command: Optional[str] = None # For stdio servers
|
|
15
|
+
args: Optional[List[str]] = None # Command arguments
|
|
16
|
+
env: Optional[Dict[str, str]] = None # Environment variables
|
|
17
|
+
|
|
18
|
+
# Authentication
|
|
19
|
+
auth_type: Optional[str] = None # "oauth", "bearer", "basic", "api_key", "none"
|
|
20
|
+
auth_config: Dict[str, Any] = field(default_factory=dict)
|
|
21
|
+
# A token supplier hook the HTTP client will call to add headers (set by OAuthManager)
|
|
22
|
+
token_supplier: Optional[Callable[[], Optional[str]]] = None
|
|
23
|
+
|
|
24
|
+
# Transport type
|
|
25
|
+
transport: str = "auto" # "auto", "stdio", "http", "sse" or "unix"
|
|
26
|
+
base_path: Optional[str] = None # Base path for HTTP/SSE endpoints
|
|
27
|
+
events_path: Optional[str] = None # SSE events path
|
|
28
|
+
# URL for Unix socket (for unix transport)
|
|
29
|
+
socket_path: Optional[str] = None
|
|
30
|
+
|
|
31
|
+
# Additional headers for HTTP transports
|
|
32
|
+
headers: Dict[str, str] = field(default_factory=dict)
|
|
33
|
+
|
|
34
|
+
# Connection settings
|
|
35
|
+
timeout: float = 30.0
|
|
36
|
+
retry_count: int = 3
|
|
37
|
+
startup_delay: float = 0.5
|
|
38
|
+
|
|
39
|
+
# Tool filtering
|
|
40
|
+
allowed_tools: Optional[List[str]] = None
|
|
41
|
+
blocked_tools: Optional[List[str]] = None
|
|
42
|
+
|
|
43
|
+
# Process management
|
|
44
|
+
kill_timeout: float = 5.0
|
|
45
|
+
|
|
46
|
+
# QUIC Configuration
|
|
47
|
+
quic_config: Any = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MCPAuthHandler:
|
|
51
|
+
"""Handles various authentication types for MCP servers."""
|
|
52
|
+
|
|
53
|
+
def __init__(self, auth_type: str, auth_config: Dict[str, Any]):
|
|
54
|
+
self.auth_type = auth_type.lower() if auth_type else None
|
|
55
|
+
self.auth_config = auth_config
|
|
56
|
+
self.logger = logging.getLogger("MCPAuthHandler")
|
|
57
|
+
|
|
58
|
+
async def get_auth_headers(self) -> Dict[str, str]:
|
|
59
|
+
"""Get authentication headers based on auth type."""
|
|
60
|
+
if not self.auth_type or self.auth_type == "none":
|
|
61
|
+
return {}
|
|
62
|
+
|
|
63
|
+
if self.auth_type == "bearer":
|
|
64
|
+
return await self._get_bearer_headers()
|
|
65
|
+
elif self.auth_type == "oauth":
|
|
66
|
+
return await self._get_oauth_headers()
|
|
67
|
+
elif self.auth_type == "basic":
|
|
68
|
+
return await self._get_basic_headers()
|
|
69
|
+
elif self.auth_type == "api_key":
|
|
70
|
+
return await self._get_api_key_headers()
|
|
71
|
+
else:
|
|
72
|
+
self.logger.warning(f"Unknown auth type: {self.auth_type}")
|
|
73
|
+
return {}
|
|
74
|
+
|
|
75
|
+
async def _get_bearer_headers(self) -> Dict[str, str]:
|
|
76
|
+
"""Get Bearer token headers."""
|
|
77
|
+
token = self.auth_config.get("token") or self.auth_config.get("access_token")
|
|
78
|
+
if not token:
|
|
79
|
+
raise ValueError("Bearer authentication requires 'token' or 'access_token' in auth_config")
|
|
80
|
+
|
|
81
|
+
return {"Authorization": f"Bearer {token}"}
|
|
82
|
+
|
|
83
|
+
async def _get_oauth_headers(self) -> Dict[str, str]:
|
|
84
|
+
"""Get OAuth headers (simplified - assumes token is already available)."""
|
|
85
|
+
access_token = self.auth_config.get("access_token")
|
|
86
|
+
if not access_token:
|
|
87
|
+
# In a full implementation, you'd handle the OAuth flow here
|
|
88
|
+
raise ValueError("OAuth authentication requires 'access_token' in auth_config")
|
|
89
|
+
|
|
90
|
+
return {"Authorization": f"Bearer {access_token}"}
|
|
91
|
+
|
|
92
|
+
async def _get_basic_headers(self) -> Dict[str, str]:
|
|
93
|
+
"""Get Basic authentication headers."""
|
|
94
|
+
username = self.auth_config.get("username")
|
|
95
|
+
password = self.auth_config.get("password")
|
|
96
|
+
|
|
97
|
+
if not username or not password:
|
|
98
|
+
raise ValueError("Basic authentication requires 'username' and 'password' in auth_config")
|
|
99
|
+
|
|
100
|
+
credentials = base64.b64encode(f"{username}:{password}".encode()).decode()
|
|
101
|
+
return {"Authorization": f"Basic {credentials}"}
|
|
102
|
+
|
|
103
|
+
async def _get_api_key_headers(self) -> Dict[str, str]:
|
|
104
|
+
"""Get API key headers."""
|
|
105
|
+
api_key = self.auth_config.get("api_key")
|
|
106
|
+
header_name = self.auth_config.get("header_name", "X-API-Key")
|
|
107
|
+
use_bearer_prefix = self.auth_config.get("use_bearer_prefix", False)
|
|
108
|
+
|
|
109
|
+
if not api_key:
|
|
110
|
+
raise ValueError("API key authentication requires 'api_key' in auth_config")
|
|
111
|
+
|
|
112
|
+
# Add Bearer prefix if requested (e.g., for Fireflies API)
|
|
113
|
+
value = f"Bearer {api_key}" if use_bearer_prefix else api_key
|
|
114
|
+
return {header_name: value}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class MCPConnectionError(Exception):
|
|
118
|
+
"""MCP connection related errors."""
|
|
119
|
+
pass
|
parrot/mcp/config.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Optional, Any
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AuthMethod(str, Enum):
|
|
7
|
+
"""Authentication method for MCP server."""
|
|
8
|
+
NONE = "none"
|
|
9
|
+
API_KEY = "api_key" # Header-based API key validation
|
|
10
|
+
OAUTH2_INTERNAL = "oauth2_internal" # In-memory OAuthAuthorizationServer
|
|
11
|
+
OAUTH2_EXTERNAL = "oauth2_external" # External OAuth2 (Azure, Keycloak)
|
|
12
|
+
BEARER = "bearer" # navigator-auth session-based
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class MCPServerConfig:
|
|
17
|
+
"""Configuration for MCP server."""
|
|
18
|
+
name: str = "ai-parrot-mcp-server"
|
|
19
|
+
version: str = "1.0.0"
|
|
20
|
+
description: str = "AI-Parrot Tools via MCP Protocol"
|
|
21
|
+
|
|
22
|
+
# Server settings
|
|
23
|
+
transport: str = "stdio" # "stdio" or "http" or "unix"
|
|
24
|
+
host: str = "localhost"
|
|
25
|
+
port: int = 8080
|
|
26
|
+
socket_path: Optional[str] = None # For UNIX socket transport
|
|
27
|
+
|
|
28
|
+
# Tool filtering
|
|
29
|
+
allowed_tools: Optional[List[str]] = None
|
|
30
|
+
blocked_tools: Optional[List[str]] = None
|
|
31
|
+
|
|
32
|
+
# Logging
|
|
33
|
+
log_level: str = "INFO"
|
|
34
|
+
|
|
35
|
+
# Authentication method (replaces enable_oauth for new code)
|
|
36
|
+
auth_method: AuthMethod = AuthMethod.NONE
|
|
37
|
+
|
|
38
|
+
# API Key settings
|
|
39
|
+
api_key_header: str = "X-API-Key"
|
|
40
|
+
api_key_store: Optional[Any] = None # APIKeyStore instance
|
|
41
|
+
|
|
42
|
+
# External OAuth2 settings (for OAUTH2_EXTERNAL)
|
|
43
|
+
oauth2_issuer_url: Optional[str] = None
|
|
44
|
+
oauth2_introspection_endpoint: Optional[str] = None
|
|
45
|
+
oauth2_client_id: Optional[str] = None
|
|
46
|
+
oauth2_client_secret: Optional[str] = None
|
|
47
|
+
oauth2_resource_server_url: Optional[str] = None
|
|
48
|
+
|
|
49
|
+
# OAuth / Authorization (for OAUTH2_INTERNAL, backward compatible)
|
|
50
|
+
enable_oauth: bool = False # Deprecated: use auth_method instead
|
|
51
|
+
oauth_scopes: Optional[List[str]] = None
|
|
52
|
+
oauth_token_ttl: int = 3600
|
|
53
|
+
oauth_code_ttl: int = 600
|
|
54
|
+
oauth_allow_dynamic_registration: bool = True
|
|
55
|
+
|
|
56
|
+
# base path for HTTP transport
|
|
57
|
+
base_path: str = "/mcp"
|
|
58
|
+
# custom events path for SSE (optional)
|
|
59
|
+
events_path: Optional[str] = None
|
|
60
|
+
|
|
61
|
+
# For Future gRPC implementation (expected)
|
|
62
|
+
grpc_host: Optional[str] = None
|
|
63
|
+
grpc_port: Optional[int] = None
|
|
64
|
+
grpc_use_tls: bool = True
|
|
65
|
+
grpc_cert_path: Optional[str] = None
|
|
66
|
+
grpc_use_protobuf: bool = False # Use native protobuf vs JSON-RPC wrapper
|
|
67
|
+
|
|
68
|
+
# QUIC transport settings
|
|
69
|
+
quic_cert_path: Optional[str] = None
|
|
70
|
+
quic_key_path: Optional[str] = None
|
|
71
|
+
quic_serialization: str = "msgpack" # "json" or "msgpack"
|
|
72
|
+
quic_enable_0rtt: bool = True
|
|
73
|
+
quic_max_datagram_size: int = 65536
|
|
74
|
+
quic_idle_timeout: float = 60.0
|
|
75
|
+
quic_webtransport_path: str = "/mcp"
|