-
Notifications
You must be signed in to change notification settings - Fork 5
fix: intermediate Palette MCP server tuorial #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
karl-cardenas-coding
wants to merge
10
commits into
main
Choose a base branch
from
mcp
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
85175b4
fix: add content for intermediate mcp tutorial
karl-cardenas-coding 1330315
chore: fix husky warning
karl-cardenas-coding 13d5556
chore: comment out agents
karl-cardenas-coding a41e5ca
chore: name update
karl-cardenas-coding a9f5de2
chore: cleanup
karl-cardenas-coding cdc9f75
chore: updates to flags
karl-cardenas-coding 242072f
chore: commented out pieces ready
karl-cardenas-coding 6e9b557
chore: updated README
karl-cardenas-coding d4ba6c0
ci: updated taskfile
karl-cardenas-coding 704a727
chore: update to not tag manually (#90)
karl-cardenas-coding File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,5 +11,7 @@ project { | |
| header_ignore = [ | ||
| # "vendors/**", | ||
| # "**autogen**", | ||
| ".venv", | ||
| "__pycache__" | ||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1 @@ | ||
| #!/usr/bin/env sh | ||
| . "$(dirname -- "$0")/_/husky.sh" | ||
| npx --no -- commitlint --edit '' | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I refuse to work with Makefile after learning about Taskfiles 😅 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # Copyright (c) Spectro Cloud | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| version: "3" | ||
|
|
||
| dotenv: [".env"] | ||
|
|
||
| tasks: | ||
| init: | ||
| desc: Install dependencies and setup the project | ||
| cmds: | ||
| - echo "initializing npm dependencies" | ||
| - npm ci | ||
| - npx husky install | ||
|
|
||
| help: | ||
| desc: Display this help | ||
| cmds: | ||
| - task --list | ||
|
|
||
| build-docker: | ||
| desc: Build docker image | ||
| cmds: | ||
| - echo "Building docker image" | ||
| - | | ||
| docker build --build-arg PALETTE_VERSION=$PALETTE_VERSION \ | ||
| --build-arg PALETTE_CLI_VERSION=$PALETTE_CLI_VERION \ | ||
| --build-arg PALETTE_EDGE_VERSION=$PALETTE_EDGE_VERSION \ | ||
| --build-arg PACKER_VERSION=$PACKER_VERSION \ | ||
| --build-arg ORAS_VERSION=$ORAS_VERSION \ | ||
| --build-arg TERRAFORM_VERSION=$TERRAFORM_VERSION \ | ||
| --build-arg K9S_VERSION=$K9S_VERSION \ | ||
| -t tutorials . | ||
|
|
||
| license: | ||
| desc: Adds a license header to all files. Reference https://github.com/hashicorp/copywrite to learn more. | ||
| cmds: | ||
| - echo "Applying license headers..." | ||
| - copywrite headers |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 3.12 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # Integrate Palette MCP | ||
|
|
||
| This folder contains the demo code for the Integrate Palette MCP in an Agentic Workflow tutorial. The user will learn how to integrate Palette MCP into a LangChain agent workflow. | ||
|
|
||
| The workflow is as follows: it identifies if a specific pack is present in your environment's cluster profiles and deployed clusters. If the pack is present, the workflow will ask you what tags you want to apply to the cluster profiles containing the pack and any active clusters using cluster | ||
| profiles containing the pack. This will allow to more readily identify the cluster profiles and active clusters that are | ||
| using the pack. | ||
|
|
||
| ## Get Started | ||
|
|
||
| Follow the instructions in the tutorial to get started. | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | Example | | ||
| | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | ||
| | `OPENAI_API_KEY` | OpenAI API key. Required. | `sk-...` | | ||
| | `OPENAI_MODEL` | Default model used for all agents. Overridden per-agent by the model-specific variables below. | `gpt-4o` | | ||
| | `OPENAI_ACTIVE_CLUSTER_MODEL` | Model for the active cluster finder agent. Falls back to `OPENAI_MODEL`. | `gpt-4o-mini` | | ||
| | `OPENAI_REPORTER_MODEL` | Model for the reporter agent. Falls back to `OPENAI_MODEL`. | `gpt-4o-mini` | | ||
| | `OPENAI_TAGGING_MODEL` | Model for the tagging agent. Falls back to `OPENAI_MODEL`. | `gpt-4o-mini` | | ||
| | `PACK_NAME` | Target pack name to search for in cluster profiles. Can also be set via `--pack`. | `nginx` | | ||
| | `DEBUG` | Log level. Accepted values: `warn`, `info`, `debug`, `verbose`. Defaults to `info`. Can also be set via `--log-level`. | `debug` | | ||
| | `PALETTE_MCP_ENV_FILE` | Path to the env file passed to the Palette MCP container. Defaults to `~/.palette/.env-mcp`. | `/home/user/.palette/.env-mcp` | | ||
| | `PALETTE_MCP_KUBECONFIG_DIR` | Path to a local directory to bind-mount into the container as `/tmp/kubeconfig`. Omitted if not set. | `/home/user/.kube` | | ||
| | `PALETTE_MCP_IMAGE` | Palette MCP container image to use. Defaults to `public.ecr.aws/palette-ai/palette-mcp-server:latest`. | `public.ecr.aws/palette-ai/palette-mcp-server:v1.2.0` | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| version: "3" | ||
|
|
||
| dotenv: [".env", "../../../.env"] | ||
|
|
||
| tasks: | ||
| start-agent: | ||
| desc: "Start the Palette MCP LangChain agent. Usage: task start-agent -- --pack <name> [--model <model>]" | ||
| env: | ||
| DEBUG: "info" | ||
| PACK_NAME: "{{.PACK_NAME}}" | ||
| OPENAI_MODEL: "{{.OPENAI_MODEL}}" | ||
| cmds: | ||
| - uv run python main.py {{.CLI_ARGS}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Copyright (c) Spectro Cloud | ||
| # SPDX-License-Identifier: Apache-2.0 |
98 changes: 98 additions & 0 deletions
98
ai/palette-mcp/integrate-palette-mcp/agents/active_cluster_agent.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # Copyright (c) Spectro Cloud | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Palette-focused agent for active cluster mapping.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import importlib | ||
| import json | ||
| from typing import Any | ||
|
|
||
| from pydantic import BaseModel | ||
|
|
||
| from helpers import suppress_console_output | ||
|
|
||
| ACTIVE_CLUSTER_SYSTEM_PROMPT = ( | ||
| "You are a Palette active-cluster mapping specialist. " | ||
| "Use only Palette MCP tools to identify active clusters that use a provided set of cluster profile UIDs. " | ||
| "Return factual results only." | ||
| ) | ||
|
|
||
|
|
||
| class ActiveCluster(BaseModel): | ||
| uid: str | ||
| name: str | ||
| cluster_profile_uid: str | ||
| cluster_profile_name: str | ||
| evidence_field_path: str | ||
| evidence: str | ||
|
|
||
|
|
||
| class ActiveClusterOutput(BaseModel): | ||
| pack_name: str | ||
| target_profile_uids: list[str] | ||
| total_active_clusters_scanned: int | ||
| active_clusters_using_matched_profiles: list[ActiveCluster] | ||
| checked_active_cluster_uids: list[str] | ||
| notes: str | ||
|
|
||
|
|
||
| # async def initialize_active_cluster_agent( | ||
| # model: str, | ||
| # mcp_tools: list, | ||
| # ) -> Any: | ||
| # from langchain.agents import create_agent | ||
| # from langchain_openai import ChatOpenAI | ||
|
|
||
| # checkpoint_module = importlib.import_module("langgraph.checkpoint.memory") | ||
| # InMemorySaver = checkpoint_module.InMemorySaver | ||
|
|
||
| # llm = ChatOpenAI(model=model) | ||
| # return create_agent( | ||
| # model=llm, | ||
| # tools=mcp_tools, | ||
| # system_prompt=ACTIVE_CLUSTER_SYSTEM_PROMPT, | ||
| # response_format=ActiveClusterOutput, | ||
| # checkpointer=InMemorySaver(), | ||
| # ) | ||
|
|
||
|
|
||
| # async def invoke_active_cluster_agent( | ||
| # agent: Any, | ||
| # pack_name: str, | ||
| # matched_profiles_output: str, | ||
| # debug_level: str, | ||
| # run_id: str, | ||
| # ) -> str: | ||
| # hide_mcp_output = debug_level != "verbose" | ||
| # schema = json.dumps(ActiveClusterOutput.model_json_schema(), indent=2) | ||
| # active_cluster_prompt = ( | ||
| # f"Given this profile discovery result for pack '{pack_name}':\n" | ||
| # f"{matched_profiles_output}\n\n" | ||
| # "Required process:\n" | ||
| # "1) Extract matched profile UIDs from the input JSON.\n" | ||
| # "2) Call gather_or_delete_clusters with action='list' and active_only=true.\n" | ||
| # "3) For each active cluster uid from step 2, call gather_or_delete_clusters with action='get'.\n" | ||
| # "4) Match clusters using explicit profile UID fields only.\n" | ||
| # "5) If no clusters match, return an empty list and include every checked active cluster uid.\n\n" | ||
| # "Return a response that conforms to this JSON schema:\n" | ||
| # f"{schema}\n" | ||
| # ) | ||
| # run_config = { | ||
| # "configurable": {"thread_id": f"active-cluster:{pack_name.lower()}:{run_id}"} | ||
| # } | ||
| # with suppress_console_output(hide_mcp_output): | ||
| # result = await agent.ainvoke( | ||
| # {"messages": [{"role": "user", "content": active_cluster_prompt}]}, | ||
| # config=run_config, | ||
| # ) | ||
| # structured = result.get("structured_response") | ||
| # if isinstance(structured, ActiveClusterOutput): | ||
| # return structured.model_dump_json() | ||
| # messages = result.get("messages", []) | ||
| # for message in reversed(messages): | ||
| # content = getattr(message, "content", None) | ||
| # if isinstance(content, str) and content.strip(): | ||
| # return content | ||
| # return str(result) |
98 changes: 98 additions & 0 deletions
98
ai/palette-mcp/integrate-palette-mcp/agents/palette_profile_agent.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # Copyright (c) Spectro Cloud | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Palette-focused agent for cluster profile discovery.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import importlib | ||
| import json | ||
| from typing import Any, Literal | ||
|
|
||
| from pydantic import BaseModel | ||
|
|
||
| from helpers import suppress_console_output | ||
|
|
||
| PROFILE_FINDER_SYSTEM_PROMPT = ( | ||
| "You are a Palette profile discovery specialist. " | ||
| "Use only Palette MCP tools to find cluster profiles that include a target pack. " | ||
| "First list cluster profiles, then inspect details when needed. " | ||
| "Always capture and return cluster profile scope. " | ||
| "Return factual results only." | ||
| ) | ||
|
|
||
|
|
||
| class MatchedProfile(BaseModel): | ||
| uid: str | ||
| name: str | ||
| scope: Literal["tenant", "project", "system", "unknown"] | ||
| pack_references: list[str] | ||
| evidence: str | ||
|
|
||
|
|
||
| class ProfileDiscoveryOutput(BaseModel): | ||
| pack_name: str | ||
| total_profiles_scanned: int | ||
| matched_profiles: list[MatchedProfile] | ||
| notes: str | ||
|
|
||
|
|
||
| # async def initialize_profile_finder_agent( | ||
| # model: str, | ||
| # mcp_tools: list, | ||
| # ) -> Any: | ||
| # from langchain.agents import create_agent | ||
| # from langchain_openai import ChatOpenAI | ||
|
|
||
| # checkpoint_module = importlib.import_module("langgraph.checkpoint.memory") | ||
| # InMemorySaver = checkpoint_module.InMemorySaver | ||
|
|
||
| # llm = ChatOpenAI(model=model) | ||
| # return create_agent( | ||
| # model=llm, | ||
| # tools=mcp_tools, | ||
| # system_prompt=PROFILE_FINDER_SYSTEM_PROMPT, | ||
| # response_format=ProfileDiscoveryOutput, | ||
| # checkpointer=InMemorySaver(), | ||
| # ) | ||
|
|
||
|
|
||
| # async def invoke_profile_finder_agent( | ||
| # agent: Any, | ||
| # pack_name: str, | ||
| # debug_level: str, | ||
| # run_id: str, | ||
| # ) -> str: | ||
| # hide_mcp_output = debug_level != "verbose" | ||
| # schema = json.dumps(ProfileDiscoveryOutput.model_json_schema(), indent=2) | ||
| # profile_finder_prompt = ( | ||
| # "Find all cluster profiles in Palette that use the pack named " | ||
| # f"'{pack_name}'. Use Palette MCP tools only.\n\n" | ||
| # "Required process:\n" | ||
| # "1) Call gather_or_delete_clusterprofiles with action='list'.\n" | ||
| # "2) If list output lacks pack details, call action='get' for relevant cluster profile uids.\n" | ||
| # "3) Match pack name case-insensitively.\n" | ||
| # "4) For each matched profile, include scope from metadata.annotations.scope when available.\n" | ||
| # "5) If scope is missing, set scope to 'unknown' and mention in notes.\n\n" | ||
| # "Important:\n" | ||
| # "- Return only profile-level results. Do not query clusters in this agent.\n\n" | ||
| # "Return a response that conforms to this JSON schema:\n" | ||
| # f"{schema}\n" | ||
| # ) | ||
| # run_config = { | ||
| # "configurable": {"thread_id": f"profile-finder:{pack_name.lower()}:{run_id}"} | ||
| # } | ||
| # with suppress_console_output(hide_mcp_output): | ||
| # result = await agent.ainvoke( | ||
| # {"messages": [{"role": "user", "content": profile_finder_prompt}]}, | ||
| # config=run_config, | ||
| # ) | ||
| # structured = result.get("structured_response") | ||
| # if isinstance(structured, ProfileDiscoveryOutput): | ||
| # return structured.model_dump_json() | ||
| # messages = result.get("messages", []) | ||
| # for message in reversed(messages): | ||
| # content = getattr(message, "content", None) | ||
| # if isinstance(content, str) and content.strip(): | ||
| # return content | ||
| # return str(result) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This addresses a deprecation warning