Skip to main content
Glama

MCP-PIF Server

by hungryrobot1
GUIDE.md15.5 kB
# MCP-PIF User Guide This guide provides detailed patterns, examples, and best practices for working with MCP-PIF. ## Table of Contents 1. [Tool Composition Patterns](#tool-composition-patterns) 2. [Advanced Metaprogramming](#advanced-metaprogramming) 3. [Working with Lists](#working-with-lists) 4. [Recursion Strategies](#recursion-strategies) 5. [Common Pitfalls](#common-pitfalls) ## Tool Composition Patterns ### Basic Composition The simplest form of composition is applying one tool to the result of another: ```json // Compose double and square: (x * 2)² { "name": "evolve", "arguments": { "name": "double_then_square", "description": "Doubles then squares", "code": { "lam": "x", "body": { "app": { "func": {"eval": {"code_of": "square"}}, "arg": {"app": {"func": {"eval": {"code_of": "double"}}, "arg": {"var": "x"}}} } } } } } ``` ### Generic Compose Function Create a higher-order compose tool: ```json { "name": "evolve", "arguments": { "name": "compose", "description": "Composes two functions f and g into f(g(x))", "code": { "lam": "f", "body": { "lam": "g", "body": { "lam": "x", "body": { "app": { "func": {"var": "f"}, "arg": {"app": {"func": {"var": "g"}, "arg": {"var": "x"}}} } } } } } } } // Use it to compose tools { "name": "run", "arguments": { "code": { "app": { "func": {"app": { "func": {"app": {"func": {"eval": {"code_of": "compose"}}, "arg": {"eval": {"code_of": "square"}}}}, "arg": {"eval": {"code_of": "double"}} }}, "arg": 5 } }, "input": null } } // Result: 100 (5 * 2 = 10, 10² = 100) ``` ### Pipeline Builder Build complex pipelines from tool lists: ```json { "name": "evolve", "arguments": { "name": "pipeline", "description": "Applies a list of functions in sequence", "code": { "lam": "funcs", "body": { "lam": "x", "body": { "fold": [ {"lam": "acc_f", "body": { "app": {"func": {"snd": {"var": "acc_f"}}, "arg": {"fst": {"var": "acc_f"}}} }}, {"var": "x"}, {"var": "funcs"} ] } } } } } ``` ### Partial Application Factory Create specialized versions of tools: ```json { "name": "evolve", "arguments": { "name": "make_adder", "description": "Creates an adder function for a specific value", "code": { "lam": "n", "body": { "lam": "x", "body": {"add": [{"var": "x"}, {"var": "n"}]} } } } } // Create add5 tool { "name": "run", "arguments": { "code": { "app": { "func": {"app": {"func": {"eval": {"code_of": "make_adder"}}, "arg": 5}}, "arg": 10 } }, "input": null } } // Result: 15 ``` ## Advanced Metaprogramming ### Code Transformation Transform existing tools by modifying their AST: ```json { "name": "evolve", "arguments": { "name": "memoize_wrapper", "description": "Wraps a function with memoization logic", "code": { "lam": "tool_name", "body": { "lam": "x", "body": { "if": { "cond": {"eq": [{"var": "x"}, 0]}, "then": 0, "else": { "app": { "func": {"eval": {"var": "tool_code"}}, "arg": {"var": "x"} } } } } } } } } ``` ### Tool Analyzer Analyze tool complexity: ```json { "name": "evolve", "arguments": { "name": "list_depth", "description": "Calculate maximum depth of nested lists", "code": { "lam": "list", "body": { "fold": [ {"lam": "max_item", "body": { "if": { "cond": {"and": [ {"not": {"eq": [{"snd": {"var": "max_item"}}, {"nil": true}]}}, {"not": {"isEmpty": {"snd": {"var": "max_item"}}}} ]}, "then": { "if": { "cond": {"gt": [ {"add": [1, {"app": {"func": {"self": true}, "arg": {"snd": {"var": "max_item"}}}}]}, {"fst": {"var": "max_item"}} ]}, "then": {"add": [1, {"app": {"func": {"self": true}, "arg": {"snd": {"var": "max_item"}}}}]}, "else": {"fst": {"var": "max_item"}} } }, "else": {"fst": {"var": "max_item"}} } }}, 0, {"var": "list"} ] } } } } ``` ### Self-Modifying Tools Tools that evolve based on usage: ```json { "name": "evolve", "arguments": { "name": "adaptive_threshold", "description": "Adjusts threshold based on input patterns", "code": { "lam": "input", "body": { "if": { "cond": {"gt": [{"var": "input"}, 100]}, "then": { "pair": [ {"var": "input"}, {"quote": {"gt": [{"var": "x"}, 100]}} ] }, "else": { "pair": [ {"var": "input"}, {"quote": {"gt": [{"var": "x"}, 50]}} ] } } } } } } ``` ## Working with Lists ### List Comprehensions Filter and transform lists: ```json { "name": "evolve", "arguments": { "name": "filter_map", "description": "Filters then maps over a list", "code": { "lam": "pred", "body": { "lam": "f", "body": { "lam": "list", "body": { "fold": [ {"lam": "acc_item", "body": { "if": { "cond": {"app": {"func": {"var": "pred"}, "arg": {"snd": {"var": "acc_item"}}}}, "then": { "cons": { "head": {"app": {"func": {"var": "f"}, "arg": {"snd": {"var": "acc_item"}}}}, "tail": {"fst": {"var": "acc_item"}} } }, "else": {"fst": {"var": "acc_item"}} } }}, {"nil": true}, {"var": "list"} ] } } } } } } ``` ### Zip Lists Combine two lists pairwise: ```json { "name": "evolve", "arguments": { "name": "zip", "description": "Zips two lists into pairs", "code": { "lam": "list1", "body": { "lam": "list2", "body": { "if": { "cond": {"or": [ {"isEmpty": {"var": "list1"}}, {"isEmpty": {"var": "list2"}} ]}, "then": {"nil": true}, "else": { "cons": { "head": {"pair": [ {"head": {"var": "list1"}}, {"head": {"var": "list2"}} ]}, "tail": {"app": { "func": {"app": {"func": {"self": true}, "arg": {"tail": {"var": "list1"}}}}, "arg": {"tail": {"var": "list2"}} }} } } } } } } } } ``` ### List Sorting Sorting algorithms like quicksort don't fit well with the continuation model because they require multiple recursive calls in a single step (sorting both the "less than" and "greater than" sublists). **Option 1: Use direct recursion with `self`** (limited by fuel): - Works for small lists (< 100 elements) - Simple to write but will hit fuel limits on larger data **Option 2: Use iterative algorithms** (recommended): - Implement bubble sort, insertion sort, or selection sort - These use a single recursive call per step - More naturally fit the continuation model **Option 3: Use `fold` for insertion sort:** ```json { "name": "evolve", "arguments": { "name": "insertion_sort", "description": "Sort list using insertion", "code": { "lam": "list", "body": { "fold": [ {"lam": "sorted_item", "body": { "fold": [ {"lam": "acc_elem", "body": { "if": { "cond": {"lt": [{"snd": {"var": "sorted_item"}}, {"snd": {"var": "acc_elem"}}]}, "then": { "pair": [ {"cons": {"head": {"snd": {"var": "acc_elem"}}, "tail": {"fst": {"var": "acc_elem"}}}}, {"snd": {"var": "sorted_item"}} ] }, "else": { "pair": [ {"cons": {"head": {"snd": {"var": "acc_elem"}}, "tail": {"fst": {"var": "acc_elem"}}}}, {"snd": {"var": "acc_elem"}} ] } } }}, {"pair": [{"nil": true}, {"snd": {"var": "sorted_item"}}]}, {"fst": {"var": "sorted_item"}} ] }}, {"nil": true}, {"var": "list"} ] } } } } ``` This approach works with any list size and doesn't require recursion. ## Recursion Strategies ### Tail Recursion Optimize recursion with accumulators: ```json { "name": "evolve", "arguments": { "name": "sum", "description": "Tail-recursive sum of a list", "code": { "lam": "list_acc", "body": { "if": { "cond": {"isEmpty": {"fst": {"var": "list_acc"}}}, "then": {"snd": {"var": "list_acc"}}, "else": { "continue": { "input": { "pair": [ {"tail": {"fst": {"var": "list_acc"}}}, {"add": [{"snd": {"var": "list_acc"}}, {"head": {"fst": {"var": "list_acc"}}}]} ] } } } } } } } } ``` **Usage:** ```json { "name": "run", "arguments": { "code": "sum", "input": {"pair": [[1, 2, 3, 4, 5], 0]} } } // Returns: 15 ``` **Key change:** Single parameter `list_acc` that is a pair, instead of two curried parameters. ### Mutual Recursion Tools that call each other: ```json // Even checker { "name": "evolve", "arguments": { "name": "is_even", "description": "Checks if a number is even", "code": { "lam": "n", "body": { "if": { "cond": {"eq": [{"var": "n"}, 0]}, "then": true, "else": { "app": { "func": {"eval": {"code_of": "is_odd"}}, "arg": {"sub": [{"var": "n"}, 1]} } } } } } } } // Odd checker { "name": "evolve", "arguments": { "name": "is_odd", "description": "Checks if a number is odd", "code": { "lam": "n", "body": { "if": { "cond": {"eq": [{"var": "n"}, 0]}, "then": false, "else": { "app": { "func": {"eval": {"code_of": "is_even"}}, "arg": {"sub": [{"var": "n"}, 1]} } } } } } } } ``` ## Common Pitfalls ### 1. Forgetting eval with code_of ```json // WRONG - code_of returns quoted code {"app": {"func": {"code_of": "square"}, "arg": 5}} // RIGHT - eval executes the quoted code {"app": {"func": {"eval": {"code_of": "square"}}, "arg": 5}} ``` ### 2. Misunderstanding Fold's Pair Parameter ```json // WRONG - expecting two parameters {"fold": [ {"lam": "acc", "body": {"lam": "x", "body": {...}}}, 0, list ]} // RIGHT - single pair parameter {"fold": [ {"lam": "acc_x", "body": { "add": [{"fst": {"var": "acc_x"}}, {"snd": {"var": "acc_x"}}] }}, 0, list ]} ``` ### 3. Continue Without Tool Context ```json // WRONG - continue in inline lambda { "name": "run", "arguments": { "code": {"lam": "x", "body": {"continue": {"input": 5}}}, "input": 10 } } // RIGHT - continue in registered tool { "name": "evolve", "arguments": { "name": "my_recursive", "code": {"lam": "x", "body": {"continue": {"input": 5}}} } } ``` ### 4. Environment Confusion in Eval ```json // System variables are cleaned {"eval": {"quote": {"self": true}}} // FAILS // User variables are preserved {"lam": "x", "body": { "eval": {"quote": {"var": "x"}} // WORKS }} ``` ### 5. String vs Object in run ```json // Tool name as string {"name": "run", "arguments": {"code": "square", "input": 5}} // Inline code as object {"name": "run", "arguments": { "code": {"lam": "x", "body": {"mul": [{"var": "x"}, {"var": "x"}]}}, "input": 5 }} // NOT a stringified JSON {"name": "run", "arguments": { "code": "{\"lam\": \"x\", \"body\": {\"mul\": [{\"var\": \"x\"}, {\"var\": \"x\"}]}}", "input": 5 }} ``` ## Understanding Continue: The Most Important Concept The `continue` primitive is often misunderstood. Here's what you need to know: ### What Continue IS: - **A pause button for evaluation** - **A marker that says "call this tool again with new input"** - **An MCP protocol-level operation** - **A way to make recursion observable and interruptible** ### What Continue IS NOT: - ❌ NOT a function call that returns a value - ❌ NOT a way to get the result of a recursive computation - ❌ NOT usable inside arithmetic or other expressions - ❌ NOT a replacement for `self` in all cases ### Critical Rule: **`continue` must be the final return value of your function.** You cannot use the result of `continue` in any computation. #### ❌ WRONG: ```json { "else": { "mul": [ {"var": "n"}, {"continue": {"input": {"sub": [{"var": "n"}, 1]}}} // ERROR! ] } } ``` This produces: `TypeError "Arithmetic expects integers"` because `continue` returns an `RContinuation`, not a number. #### ✅ RIGHT: ```json { "else": { "continue": { "input": { "pair": [ {"sub": [{"var": "n"}, 1]}, {"mul": [{"var": "n"}, {"var": "acc"}]} // Computation happens HERE ] } } } } ``` All computation happens BEFORE `continue`, stored in the accumulator. ### When to Use Each Recursion Method: | Method | Use When | Pros | Cons | |--------|----------|------|------| | **`continue`** | Deep recursion (n > 100) | Observable, no fuel issues | Requires accumulator pattern | | **`self`** | Shallow recursion (n < 20) | Natural, returns values | Fuel-limited, not observable | | **`eval` + `code_of`** | Mutual recursion | Works across tools | Medium fuel cost | ## Best Practices 1. **Name tools descriptively**: Use clear names that indicate what the tool does 2. **Document complex tools**: Add detailed descriptions for non-obvious behavior 3. **Test incrementally**: Build complex tools from simpler, tested components 4. **Use type-like naming**: `list_to_pairs`, `int_to_string` helps track data flow 5. **Leverage metaprogramming carefully**: Code generation is powerful but can obscure logic 6. **Monitor fuel usage**: Complex recursive tools may need fuel limit adjustments 7. **Compose, don't complicate**: Many small tools > one complex tool 8. **Use the help system**: `{"name": "help", "arguments": {"category": "lists"}}` for reference ## Next Steps - Explore the primitives.json file for the complete primitive reference - Read the architecture documentation in README.md - Experiment with the debug mode (`MCP_DEBUG=1`) to understand evaluation - Try building your own domain-specific tool libraries

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/hungryrobot1/MCP-PIF'

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