Skip to main content
Glama
knishioka

Treasure Data MCP Server

by knishioka

td_find_project

Search for Treasure Data projects by name to retrieve project IDs and metadata, enabling operations like downloading archives when you know the project name but not the exact ID.

Instructions

Find project by name when you don't know the exact ID.

Searches all projects and returns matches. Useful when you know project
name but need the ID for other operations like downloading archives.

Common scenarios:
- User mentions project name, need to find ID
- Looking for projects containing specific keywords
- Getting project ID before using td_download_project_archive
- Finding multiple projects with similar names

Use exact_match=True for precise name matching, False for fuzzy search.
Returns project IDs, names, and metadata for all matches.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
search_termYes
exact_matchNo

Implementation Reference

  • The async handler function that implements td_find_project tool. It searches for projects by name in both projects and workflows lists using TD client, supporting exact and fuzzy matching, and returns matching projects with metadata.
    async def td_find_project(
        search_term: str,
        exact_match: bool = False,
    ) -> dict[str, Any]:
        """Find project by name when you don't know the exact ID.
    
        Searches all projects and returns matches. Useful when you know project
        name but need the ID for other operations like downloading archives.
    
        Common scenarios:
        - User mentions project name, need to find ID
        - Looking for projects containing specific keywords
        - Getting project ID before using td_download_project_archive
        - Finding multiple projects with similar names
    
        Use exact_match=True for precise name matching, False for fuzzy search.
        Returns project IDs, names, and metadata for all matches.
        """
        if not search_term or not search_term.strip():
            return _format_error_response("Search term cannot be empty")
    
        client = _create_client(include_workflow=True)
        if isinstance(client, dict):
            return client
    
        try:
            # First, try to get projects directly (up to 200)
            projects = client.get_projects(limit=200, all_results=True)
    
            found_projects = []
            search_lower = search_term.lower()
    
            for project in projects:
                project_name = project.name.lower()
    
                if exact_match:
                    if project_name == search_lower:
                        found_projects.append(project)
                else:
                    if search_lower in project_name:
                        found_projects.append(project)
    
            if found_projects:
                return {
                    "found": True,
                    "count": len(found_projects),
                    "projects": [
                        {
                            "id": p.id,
                            "name": p.name,
                            "created_at": p.created_at,
                            "updated_at": p.updated_at,
                        }
                        for p in found_projects
                    ],
                }
    
            # If not found in projects, search through workflows
            workflows = client.get_workflows(count=1000, all_results=True)
    
            project_map = {}
            for workflow in workflows:
                project_name = workflow.project.name
                project_id = workflow.project.id
    
                if exact_match:
                    if project_name.lower() == search_lower:
                        if project_id not in project_map:
                            project_map[project_id] = {
                                "id": project_id,
                                "name": project_name,
                                "workflow_count": 0,
                            }
                        project_map[project_id]["workflow_count"] += 1
                else:
                    if search_lower in project_name.lower():
                        if project_id not in project_map:
                            project_map[project_id] = {
                                "id": project_id,
                                "name": project_name,
                                "workflow_count": 0,
                            }
                        project_map[project_id]["workflow_count"] += 1
    
            if project_map:
                # Get full project details for found projects
                projects_with_details = []
                for project_id, project_info in project_map.items():
                    try:
                        project = client.get_project(project_id)
                        if project:
                            projects_with_details.append(
                                {
                                    "id": project.id,
                                    "name": project.name,
                                    "created_at": project.created_at,
                                    "updated_at": project.updated_at,
                                    "workflow_count": project_info["workflow_count"],
                                }
                            )
                    except Exception:
                        # Fallback to basic info
                        projects_with_details.append(project_info)
    
                return {
                    "found": True,
                    "count": len(projects_with_details),
                    "projects": projects_with_details,
                    "source": "workflows",
                }
    
            return {
                "found": False,
                "count": 0,
                "message": f"No projects found matching '{search_term}'",
            }
    
        except Exception as e:
            return _format_error_response(f"Failed to search projects: {str(e)}")
  • The registration function that sets up the MCP instance and registers td_find_project along with other search tools using the mcp.tool() decorator.
    def register_mcp_tools(
        mcp_instance, create_client_func, format_error_func, validate_project_func
    ):
        """Register MCP tools with the provided MCP instance."""
        global mcp, _create_client, _format_error_response, _validate_project_id
        mcp = mcp_instance
        _create_client = create_client_func
        _format_error_response = format_error_func
        _validate_project_id = validate_project_func
    
        # Register all tools
        mcp.tool()(td_find_project)
        mcp.tool()(td_find_workflow)
        mcp.tool()(td_get_project_by_name)
        mcp.tool()(td_smart_search)
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it searches all projects, returns matches with IDs/names/metadata, supports both exact and fuzzy matching via the exact_match parameter, and is designed for lookup operations (implied read-only, non-destructive). It doesn't mention rate limits, authentication needs, or pagination, but covers core functionality well for a search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and efficiently written. It starts with the core purpose, explains utility, lists common scenarios, provides parameter guidance, and describes returns—all in 7 concise sentences with zero wasted words. Each sentence adds value, and information is front-loaded appropriately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description does an excellent job covering the tool's context. It explains purpose, usage, parameters, and return values (project IDs, names, metadata). The main gap is lack of explicit mention of read-only/non-destructive nature (though implied), but for a search tool with 2 simple parameters, this is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds significant semantic value: it explains that 'search_term' is for project names/keywords, clarifies that 'exact_match=True' enables precise name matching while 'False' enables fuzzy search, and connects parameters to the tool's purpose. This goes well beyond the bare schema, though it doesn't detail format constraints for search_term.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Find project by name when you don't know the exact ID. Searches all projects and returns matches.' It specifies the verb ('find'), resource ('project'), and scope ('by name'), and distinguishes it from siblings like td_get_project (which likely requires ID) and td_get_project_by_name (which might be exact-match only).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool: 'Useful when you know project name but need the ID for other operations like downloading archives.' It lists common scenarios (e.g., user mentions project name, looking for keywords) and names a specific alternative use case ('Getting project ID before using td_download_project_archive'). It also distinguishes from exact-match alternatives by mentioning fuzzy search capability.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/knishioka/td-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server